Thursday Aug 16, 2007

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

Saturday May 05, 2007

JMX Web Services Connector is out, in WS-Man dress.


JMX Web Services Connector (JSR 262) RI is out! You can download it here.

The novelety in comparaison with the previous Early Access is that the Connector protocol is now based on WS-Management (WS-Man). Connector WS-Man implementation is based on the WiseMan project.

Native WS-Man clients can now interact with MBeans. MBeans are no more the exclusivity of JMX clients. Clients such as Windows Remote Manager (WinRM) and openwsman, can retrieve MBean attributes, call MBean operations and subscribe to MBean notifications.

JSR 262 specification defines a mapping between JMX MBeans and WS-Man Managed Resources. More details can be found in the Early Draft 2 specification. Have a look to the spec and send us your feedbacks.

Next Thursday, at JavaOne, during Eamonn and myself Technical Session, we are presenting an interoperability demo that highlights these new JMX interoperation capabilities. Demo is composed of three scenario:
  • HP Open View Operations / JSR 262 (done by Denis Rachal from HP)
  • Microsoft WinRM Scripting for JSR 262
  • Microsoft Vista Event Viewer to subscribe to MBeans
See you there!

Jean-Fran├žois
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