Skip to content

Commit 3cf7065

Browse files
committed
Add SSL support for JMX connector in ManagementContext
1 parent b387595 commit 3cf7065

File tree

1 file changed

+51
-4
lines changed

1 file changed

+51
-4
lines changed

activemq-broker/src/main/java/org/apache/activemq/broker/jmx/ManagementContext.java

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
import java.rmi.RemoteException;
2727
import java.rmi.registry.LocateRegistry;
2828
import java.rmi.registry.Registry;
29+
import java.rmi.server.RMIClientSocketFactory;
30+
import java.rmi.server.RMIServerSocketFactory;
2931
import java.rmi.server.UnicastRemoteObject;
3032
import java.util.LinkedList;
3133
import java.util.List;
@@ -50,8 +52,11 @@
5052
import javax.management.remote.JMXServiceURL;
5153
import javax.management.remote.rmi.RMIConnectorServer;
5254
import javax.management.remote.rmi.RMIJRMPServerImpl;
55+
import javax.rmi.ssl.SslRMIClientSocketFactory;
56+
import javax.rmi.ssl.SslRMIServerSocketFactory;
5357

5458
import org.apache.activemq.Service;
59+
import org.apache.activemq.broker.SslContext;
5560
import org.slf4j.Logger;
5661
import org.slf4j.LoggerFactory;
5762
import org.slf4j.MDC;
@@ -115,6 +120,7 @@ public class ManagementContext implements Service {
115120
private List<ObjectName> suppressMBeanList;
116121
private Remote serverStub;
117122
private RMIJRMPServerImpl server;
123+
private SslContext sslContext;
118124

119125
public ManagementContext() {
120126
this(null);
@@ -549,11 +555,28 @@ protected MBeanServer createMBeanServer() throws MalformedObjectNameException, I
549555
}
550556

551557
private void createConnector(MBeanServer mbeanServer) throws IOException {
558+
// Resolve SSL socket factories first, so they can be shared by registry and connector
559+
final RMIClientSocketFactory csf;
560+
final RMIServerSocketFactory ssf;
561+
if (sslContext != null) {
562+
try {
563+
final javax.net.ssl.SSLContext ctx = sslContext.getSSLContext();
564+
csf = new SslRMIClientSocketFactory();
565+
ssf = new SslRMIServerSocketFactory(ctx, null, null, false);
566+
LOG.info("JMX connector will use SSL from configured sslContext");
567+
} catch (Exception e) {
568+
throw new IOException("Failed to initialize SSL for JMX connector", e);
569+
}
570+
} else {
571+
csf = null;
572+
ssf = null;
573+
}
574+
552575
// Create the NamingService, needed by JSR 160
553576
try {
554577
if (registry == null) {
555578
LOG.debug("Creating RMIRegistry on port {}", connectorPort);
556-
registry = jmxRegistry(connectorPort);
579+
registry = jmxRegistry(connectorPort, csf, ssf);
557580
}
558581

559582
namingServiceObjectName = ObjectName.getInstance("naming:type=rmiregistry");
@@ -579,7 +602,7 @@ private void createConnector(MBeanServer mbeanServer) throws IOException {
579602
rmiServer = ""+getConnectorHost()+":" + rmiServerPort;
580603
}
581604

582-
server = new RMIJRMPServerImpl(connectorPort, null, null, environment);
605+
server = new RMIJRMPServerImpl(connectorPort, csf, ssf, environment);
583606

584607
final String serviceURL = "service:jmx:rmi://" + rmiServer + "/jndi/rmi://" +getConnectorHost()+":" + connectorPort + connectorPath;
585608
final JMXServiceURL url = new JMXServiceURL(serviceURL);
@@ -659,6 +682,28 @@ public void setEnvironment(Map<String, ?> environment) {
659682
this.environment = environment;
660683
}
661684

685+
/**
686+
* Get the SSL context used for the JMX connector.
687+
*/
688+
public SslContext getSslContext() {
689+
return sslContext;
690+
}
691+
692+
/**
693+
* Set the SSL context to use for the JMX connector.
694+
* When configured, the JMX RMI connector will use SSL with the
695+
* keyStore and trustStore from this context, allowing reuse of
696+
* the broker's {@code <sslContext>} configuration.
697+
*
698+
* Example XML configuration:
699+
* <pre>
700+
* &lt;managementContext createConnector="true" sslContext="#brokerSslContext"/&gt;
701+
* </pre>
702+
*/
703+
public void setSslContext(SslContext sslContext) {
704+
this.sslContext = sslContext;
705+
}
706+
662707
public boolean isAllowRemoteAddressInMBeanNames() {
663708
return allowRemoteAddressInMBeanNames;
664709
}
@@ -683,9 +728,11 @@ public String getSuppressMBean() {
683728
}
684729

685730
// do not use sun.rmi.registry.RegistryImpl! it is not always easily available
686-
private Registry jmxRegistry(final int port) throws RemoteException {
731+
private Registry jmxRegistry(final int port, final RMIClientSocketFactory csf, final RMIServerSocketFactory ssf) throws RemoteException {
687732
final var loader = Thread.currentThread().getContextClassLoader();
688-
final var delegate = LocateRegistry.createRegistry(port);
733+
final var delegate = (csf != null && ssf != null)
734+
? LocateRegistry.createRegistry(port, csf, ssf)
735+
: LocateRegistry.createRegistry(port);
689736
return Registry.class.cast(Proxy.newProxyInstance(
690737
loader == null ? getSystemClassLoader() : loader,
691738
new Class<?>[]{Registry.class}, (proxy, method, args) -> {

0 commit comments

Comments
 (0)