Securing JMX Web Services Connector


I have been contacted by a customer of the JSR 262 Early Access 2 who asked me for some material on how to enable HTTPS. I realized that no material was provided. No sample, no blog entry, nothing... Why is there such a lack of documentation? Thinking at it, it appeared that the extreme simplicity of enabling HTTPS for the WS Connector made us forget to provide material for it. This blog entry is trying to correct that and highlight the extreme simplicity enabling HTTPS.

Here, I will present in turn a JDK 5 and a JDK 6 example. The scenario is very common. You have already written a JMX agent and a JMX client. You have already tested that all your JMX MBeans are working well. It is now deployment time! And it is at this precise time that your customer asks you for Security...
You never thought that it could happen to you. You know that security is a complex topic. Encryption, symmetric or asymmetric keys are things that you have heard of but you prefer to stay away from them...
No worries, the JMX WebServices Connector takes charge of all the details. You are just required to configure it. So let's start by securing your ConnectorServer.

Securing the ConnectorServer

Your agent code looks something like :
  JMXConnectorServer server =
                JMXConnectorServerFactory.
                newJMXConnectorServer(new JMXServiceURL("service:jmx:ws:" +
                "//localhost:8080/jmxws"), null,
                ManagementFactory.getPlatformMBeanServer());

  server.start();

Right? This is the very classical way to start a JMX Connector. If this is not the case, if the way you create and start your agent is not similar to this code, please send me a mail (jean-francois dot denise at sun dot com)

So how do you enable HTTPS? Simply by changing the protocol name when creating the JMXServiceURL to be ws-secure instead of ws.

So now your code looks like :
  JMXConnectorServer server =
                JMXConnectorServerFactory.
                newJMXConnectorServer(new JMXServiceURL("service:jmx:ws-secure:" +
                "//localhost:8080/jmxws"), null,
                ManagementFactory.getPlatformMBeanServer());

  server.start();

Are you done? Not yet, you need to provide a KeyStore location and a KeyStore password for SSL to find the certificates. You don't have a KeyStore or a certificate? Not a big deal, use keytool! For example call :

keytool -genkey -keystore jsr262Keystore -keyalg RSA

Answer the questions and provide a KeyStore password. In this blog entry I am using 123456 as the password value. This is something that you should never do in a real context. In this blog entry context, however, is is safe enough.
keytool generates a file named jsr262Keystore. You have now a KeyStore that contains a certificate secured by a password.
If you are running JDK 6, it is enough to actually launch your JMX agent in a secure way. The keyStore and password are provided thanks to two standard Java properties. For example :

java -classpath ... -Djavax.net.ssl.keyStore=jsr262Keystore -Djavax.net.ssl.keyStorePassword=123456 MyJMXAgent

Simple, no? Yes, but what about if I am using JDK 5? Why isn't it so simple?
Simply because JDK 6 has been extended to support a default SSL configuration that relies on the Java properties we previously used (javax.net.ssl.keyStore and javax.net.ssl.keyStorePassword). On JDK 5, you need to provide an instance of javax.net.ssl.SSLContext. Here, I provide you with an SSLContext that reads the standard Java properties in order to compute an SSL configuration. You can use this TestSSLContext Java file that implements the required logic.

How do I pass this SSLContext to the WS ConnectorServer? By using the env map when calling the JMXConnectorServerFactory class.
Your updated source code looks like :
        // Create the SSLContext
         SSLContext ctx = TestSSLContext.getInstance("SSLv3");
        // Create an env map
        Map env = new HashMap(1);
        // Provide the SSLContext
        env.put("jmx.remote.ws.sslcontext", ctx);
        // Create the ConnectorServer providing the env map
        JMXConnectorServer server =
                JMXConnectorServerFactory.
                newJMXConnectorServer(new JMXServiceURL("service:jmx:ws-secure:" +
                "//localhost:8080/jmxws"), env,
                ManagementFactory.getPlatformMBeanServer());
        
        server.start();

You are done, you can start your JMX Agent the same way you did using JDK 6.

java -classpath ... -Djavax.net.ssl.keyStore=jsr262Keystore -Djavax.net.ssl.keyStorePassword=123456 MyJMXAgent

You have now a JMX agent running, waiting for https requests. Let's go secure the client side.

Securing the Connector

This is JDK 5 or 6 independent. You need to replace the ws protocol name with ws-secure as you did on the server side, then provide a TrustStore location and password. The KeyStore named jsr262KeyStore we previously created can be reused by the client.
Your client code looks something like :
 JMXServiceURL url = new JMXServiceURL("service:jmx:ws://localhost:8080/jmxws");
 JMXConnector connector = JMXConnectorFactory.connect(url, null);
 //Get the MBeanServerConnection
 MBeanServerConnection mbsc = connector.getMBeanServerConnection();

Once the JMXServiceURL value has been updated, you code looks like:
 JMXServiceURL url = new JMXServiceURL("service:jmx:ws-secure://localhost:8080/jmxws");
 JMXConnector connector = JMXConnectorFactory.connect(url, null);
 //Get the MBeanServerConnection
 MBeanServerConnection mbsc = connector.getMBeanServerConnection();

When starting the client you provide the TrustStore and password using two standard Java properties. For example :

java -classpath ... -Djavax.net.ssl.trustStore=jsr262Keystore -Djavax.net.ssl.trustStorePassword=123456 MyClient

And... you are done! Extremely simple, no? I hope so, otherwise, let me know ;-).

Some material

Here is all the material I created to write this blog entry. A first NetBeans project containing the source of the agent, the source of TestSSLContext (remember, this is only needed on JDK 5) and the jsr262KeyStore. A second NetBeans project containing the source of the client. You will have to correct some references (mainly JDK, JAX-WS libraries) when opening them but they can help you start securing your app.

Next blog entry to come? Why not use WS-Security (Security applied to the SOAP message) to secure JMX Web Services communication. Stay tuned.

Regards.

Jean-Francois
Comments:

Post a Comment:
Comments are closed for this entry.
About

jeanfrancoisdenise

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today