Skip to content

Commit eb24f80

Browse files
Adding support for scenarios where the RMI registry has SSL enabled (#835)
Co-authored-by: jason plumb <[email protected]>
1 parent 721d1d5 commit eb24f80

File tree

4 files changed

+86
-6
lines changed

4 files changed

+86
-6
lines changed

jmx-metrics/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@ otel.jmx.target.system = jvm,kafka
2222
otel.jmx.interval.milliseconds = 5000
2323
otel.jmx.username = my-username
2424
otel.jmx.password = my-password
25-
25+
otel.jmx.remote.registry.ssl=false
2626
otel.metrics.exporter = otlp
2727
otel.exporter.otlp.endpoint = http://my-opentelemetry-collector:4317
2828
```
2929

3030
As configured in this example, the metric gatherer will establish an MBean server connection using the
3131
specified `otel.jmx.service.url` (required) and credentials and configure an OTLP gRPC metrics exporter reporting to
32-
`otel.exporter.otlp.endpoint`. After loading the included JVM and Kafka metric-gathering scripts determined by
32+
`otel.exporter.otlp.endpoint`. If SSL is enabled on the RMI registry for your server, the `otel.jmx.remote.registry.ssl` property must be set to `true`. After loading the included JVM and Kafka metric-gathering scripts determined by
3333
the comma-separated list in `otel.jmx.target.system`, it will then run the scripts on the desired interval
3434
length of `otel.jmx.interval.milliseconds` and export the resulting metrics.
3535

jmx-metrics/src/main/groovy/io/opentelemetry/contrib/jmxmetrics/JmxClient.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import javax.management.MBeanServerConnection;
2121
import javax.management.ObjectName;
2222
import javax.management.remote.JMXConnector;
23-
import javax.management.remote.JMXConnectorFactory;
2423
import javax.management.remote.JMXServiceURL;
2524

2625
public class JmxClient {
@@ -31,6 +30,7 @@ public class JmxClient {
3130
private final String password;
3231
private final String realm;
3332
private final String remoteProfile;
33+
private final boolean registrySsl;
3434
@Nullable private JMXConnector jmxConn;
3535

3636
JmxClient(final JmxConfig config) throws MalformedURLException {
@@ -39,6 +39,7 @@ public class JmxClient {
3939
this.password = config.password;
4040
this.realm = config.realm;
4141
this.remoteProfile = config.remoteProfile;
42+
this.registrySsl = config.registrySsl;
4243
}
4344

4445
public MBeanServerConnection getConnection() {
@@ -68,7 +69,7 @@ public MBeanServerConnection getConnection() {
6869
logger.warning("SASL unsupported in current environment: " + e.getMessage());
6970
}
7071

71-
jmxConn = JMXConnectorFactory.connect(url, env);
72+
jmxConn = JmxConnectorHelper.connect(url, env, registrySsl);
7273
return jmxConn.getMBeanServerConnection();
7374
} catch (IOException e) {
7475
logger.log(Level.WARNING, "Could not connect to remote JMX server: ", e);

jmx-metrics/src/main/groovy/io/opentelemetry/contrib/jmxmetrics/JmxConfig.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class JmxConfig {
1919
static final String INTERVAL_MILLISECONDS = PREFIX + "jmx.interval.milliseconds";
2020
static final String METRICS_EXPORTER_TYPE = PREFIX + "metrics.exporter";
2121
static final String EXPORTER = PREFIX + "exporter.";
22-
22+
static final String REGISTRY_SSL = PREFIX + "jmx.remote.registry.ssl";
2323
static final String EXPORTER_INTERVAL = PREFIX + "metric.export.interval";
2424

2525
static final String OTLP_ENDPOINT = EXPORTER + "otlp.endpoint";
@@ -74,7 +74,7 @@ class JmxConfig {
7474
final String password;
7575
final String realm;
7676
final String remoteProfile;
77-
77+
final boolean registrySsl;
7878
final Properties properties;
7979

8080
JmxConfig(final Properties props) {
@@ -111,6 +111,8 @@ class JmxConfig {
111111
remoteProfile = properties.getProperty(JMX_REMOTE_PROFILE);
112112
realm = properties.getProperty(JMX_REALM);
113113

114+
registrySsl = Boolean.valueOf(properties.getProperty(REGISTRY_SSL));
115+
114116
// For the list of System Properties, if they have been set in the properties file
115117
// they need to be set in Java System Properties.
116118
JAVA_SYSTEM_PROPERTIES.forEach(
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.contrib.jmxmetrics;
7+
8+
import java.io.IOException;
9+
import java.net.URI;
10+
import java.rmi.NotBoundException;
11+
import java.rmi.registry.LocateRegistry;
12+
import java.rmi.registry.Registry;
13+
import java.util.Map;
14+
import java.util.logging.Level;
15+
import java.util.logging.Logger;
16+
import javax.management.remote.JMXConnector;
17+
import javax.management.remote.JMXConnectorFactory;
18+
import javax.management.remote.JMXServiceURL;
19+
import javax.management.remote.rmi.RMIConnector;
20+
import javax.management.remote.rmi.RMIServer;
21+
import javax.rmi.ssl.SslRMIClientSocketFactory;
22+
23+
public class JmxConnectorHelper {
24+
25+
private static final Logger logger = Logger.getLogger(JmxConnectorHelper.class.getName());
26+
27+
private static RMIServer stub = null;
28+
private static final SslRMIClientSocketFactory sslRMIClientSocketFactory =
29+
new SslRMIClientSocketFactory();
30+
31+
private JmxConnectorHelper() {}
32+
33+
/**
34+
* To use SSL, the {@link RMIServer} stub used by the {@link RMIConnector} must be built
35+
* separately. As a result, we have to unwind the {@link JMXConnectorFactory#connect} method and
36+
* reimplement pieces.
37+
*/
38+
public static JMXConnector connect(
39+
JMXServiceURL serviceURL, Map<String, Object> env, boolean registrySsl) throws IOException {
40+
41+
// Different connection logic is needed when SSL is enabled on the RMI registry
42+
if (!registrySsl) {
43+
return JMXConnectorFactory.connect(serviceURL, env);
44+
}
45+
46+
logger.log(Level.INFO, "Attempting to connect to an SSL-protected RMI registry");
47+
48+
String hostName;
49+
int port;
50+
51+
if (serviceURL.getURLPath().startsWith("/jndi/")) {
52+
final String[] components = serviceURL.getURLPath().split("/", 3);
53+
final URI uri = URI.create(components[2]);
54+
hostName = uri.getHost();
55+
port = uri.getPort();
56+
} else {
57+
hostName = serviceURL.getHost();
58+
port = serviceURL.getPort();
59+
}
60+
61+
if (stub == null) {
62+
stub = getStub(hostName, port);
63+
}
64+
JMXConnector jmxConn = new RMIConnector(stub, null);
65+
jmxConn.connect(env);
66+
return jmxConn;
67+
}
68+
69+
private static RMIServer getStub(String hostName, int port) throws IOException {
70+
try {
71+
Registry registry = LocateRegistry.getRegistry(hostName, port, sslRMIClientSocketFactory);
72+
return (RMIServer) registry.lookup("jmxrmi");
73+
} catch (NotBoundException nbe) {
74+
throw new IOException(nbe);
75+
}
76+
}
77+
}

0 commit comments

Comments
 (0)