Skip to content

Commit 016992d

Browse files
committed
GH-306 Keyring API is now used to store JMX passwords
1 parent e1a2e3d commit 016992d

File tree

4 files changed

+54
-15
lines changed

4 files changed

+54
-15
lines changed

visualvm/jmx/nbproject/project.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@
5151
<specification-version>1.48</specification-version>
5252
</run-dependency>
5353
</dependency>
54+
<dependency>
55+
<code-name-base>org.netbeans.modules.keyring</code-name-base>
56+
<build-prerequisite/>
57+
<compile-dependency/>
58+
<run-dependency>
59+
<specification-version>1.40</specification-version>
60+
</run-dependency>
61+
</dependency>
5462
<dependency>
5563
<code-name-base>org.netbeans.modules.sendopts</code-name-base>
5664
<build-prerequisite/>

visualvm/jmx/src/org/graalvm/visualvm/jmx/CredentialsProvider.java

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
import org.graalvm.visualvm.application.Application;
3333
import org.graalvm.visualvm.core.datasource.Storage;
3434
import org.graalvm.visualvm.core.datasupport.Utils;
35+
import org.graalvm.visualvm.jmx.impl.JmxApplication;
36+
import org.netbeans.api.keyring.Keyring;
3537

3638
/**
3739
* EnvironmentProvider adding the JMXConnector.CREDENTIALS property to the JMX
@@ -109,7 +111,7 @@ public Custom(String username, char[] password, boolean persistent) {
109111

110112

111113
public Map<String, ?> getEnvironment(Application application, Storage storage) {
112-
return createMap(user, pword == null ? null : Arrays.copyOf(pword, pword.length));
114+
return createMap(user, getPassword(storage));
113115
}
114116

115117
public String getEnvironmentId(Storage storage) {
@@ -120,11 +122,24 @@ public String getEnvironmentId(Storage storage) {
120122
public void saveEnvironment(Storage storage) {
121123
if (!persistent) return;
122124
storage.setCustomProperty(PROPERTY_USER, user);
123-
storage.setCustomProperty(PROPERTY_PWORD, new String(pword));
125+
String keyringId = JmxApplication.createId(null, this, storage);
126+
char[] pw = getPassword(storage);
127+
if (pw != null) {
128+
Keyring.save(keyringId, pw, "VisualVM - JMX password for "+user); // NOI18N
129+
} else {
130+
Keyring.delete(keyringId);
131+
}
124132
}
125133

126134

127135
String getUsername(Storage storage) { return user; }
136+
137+
private char[] getPassword(Storage storage) {
138+
if (hasPassword(storage)) {
139+
return decodePassword(Arrays.copyOf(pword, pword.length));
140+
}
141+
return null;
142+
}
128143

129144
boolean hasPassword(Storage storage) { return pword != null &&
130145
pword.length > 0; }
@@ -143,8 +158,7 @@ public static class Persistent extends CredentialsProvider {
143158

144159
public Map<String, ?> getEnvironment(Application application, Storage storage) {
145160
String user = storage.getCustomProperty(PROPERTY_USER);
146-
String pword = storage.getCustomProperty(PROPERTY_PWORD);
147-
return createMap(user, pword == null ? null : pword.toCharArray());
161+
return createMap(user, getPassword(storage));
148162
}
149163

150164
public String getEnvironmentId(Storage storage) {
@@ -159,9 +173,27 @@ public String getEnvironmentId(Storage storage) {
159173
String getUsername(Storage storage) { return storage.getCustomProperty(
160174
PROPERTY_USER); }
161175

162-
boolean hasPassword(Storage storage) {
176+
private char[] getPassword(Storage storage) {
177+
String keyringId = JmxApplication.createId(null, this, storage);
178+
char[] pw = Keyring.read(keyringId);
179+
if (pw != null) {
180+
return pw;
181+
}
182+
// read old settings
163183
String pword = storage.getCustomProperty(PROPERTY_PWORD);
164-
return pword != null && !pword.isEmpty();
184+
if (pword != null && !pword.isEmpty()) {
185+
// migrate old settings to Keyring
186+
// Keyring.save(keyringId, decodePassword(pword.toCharArray()), "VisualVM - JMX password for "+getUsername(storage)); // NOI18N
187+
// storage.clearCustomProperty(PROPERTY_PWORD);
188+
//return getPassword(storage);
189+
return decodePassword(pword.toCharArray());
190+
}
191+
return null;
192+
}
193+
194+
boolean hasPassword(Storage storage) {
195+
char[] pword = getPassword(storage);
196+
return pword != null && pword.length>0;
165197
}
166198

167199
boolean isPersistent(Storage storage) {
@@ -178,10 +210,9 @@ boolean isPersistent(Storage storage) {
178210
Map<String, Object> map = new HashMap<>();
179211

180212
if (username != null && !username.isEmpty()) {
181-
map.put(JMXConnector.CREDENTIALS, new String[] { username, pword == null ? null : new String(decodePassword(pword)) });
182-
} else {
183-
if (pword != null) Arrays.fill(pword, (char)0);
213+
map.put(JMXConnector.CREDENTIALS, new String[] { username, pword == null ? null : new String(pword) });
184214
}
215+
if (pword != null) Arrays.fill(pword, (char)0);
185216

186217
return map;
187218
}

visualvm/jmx/src/org/graalvm/visualvm/jmx/impl/JmxApplication.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public final class JmxApplication extends Application {
7979
// Note: storage may be null, in this case the JmxApplication isn't persistent
8080
// and creates a temporary storage just like any other regular Application
8181
public JmxApplication(Host host, JMXServiceURL url, EnvironmentProvider envProvider, Storage storage) {
82-
super(host, createId(url, envProvider, storage), STATE_UNAVAILABLE);
82+
super(host, createId(url.toString(), envProvider, storage), STATE_UNAVAILABLE);
8383
this.url = url;
8484
this.envProvider = envProvider;
8585
this.storage = storage;
@@ -166,11 +166,11 @@ public String toString() {
166166
return "JmxApplication [id: " + getId() + "]"; // NOI18N
167167
}
168168

169-
private static String createId(JMXServiceURL url, EnvironmentProvider envProvider,
169+
public static String createId(String urlId, EnvironmentProvider envProvider,
170170
Storage storage) {
171-
// url.toString will always be used
172-
String urlId = url.toString();
173-
171+
if (urlId == null) {
172+
urlId = storage.getCustomProperty(JmxApplicationProvider.PROPERTY_CONNECTION_STRING);
173+
}
174174
// No envProvider -> return just url.toString()
175175
if (envProvider == null) return urlId;
176176

visualvm/jmx/src/org/graalvm/visualvm/jmx/impl/JmxApplicationProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public class JmxApplicationProvider {
9898
CURRENT_SNAPSHOT_VERSION_MINOR;
9999

100100
public static final String PROPERTY_RETRY_WITHOUT_SSL = "prop_retry_without_ssl"; // NOI18N
101-
private static final String PROPERTY_CONNECTION_STRING = "prop_conn_string"; // NOI18N
101+
static final String PROPERTY_CONNECTION_STRING = "prop_conn_string"; // NOI18N
102102
private static final String PROPERTY_HOSTNAME = "prop_conn_hostname"; // NOI18N
103103
private static final String PROPERTY_ENV_PROVIDER_ID = "prop_env_provider_id"; // NOI18N
104104

0 commit comments

Comments
 (0)