Java Dynamic Management Kit 5.1 Tutorial

11.4.1 SASL Privacy

As stated above, Java DMK enables you to make your JMXMP connections private by using a combination of the SASL/DIGEST-MD5 profile, for user authentication and encryption, and file access control based on the MBeanServerForwarder interface, for user access level authorization.

There is an example of an JMXMP connector implementing SASL privacy in the current/Security/jmxmp/sasl_privacy directory in the main examplesDir.


Example 11–9 Implementing SASL Privacy in a JMXMP Connector Server

[...]
import javax.security.sasl.Sasl;

public class Server {

    public static void main(String[] args) {
        try {
            MBeanServer mbs = MBeanServerFactory.createMBeanServer();
            HashMap env = new HashMap();

            Security.addProvider(new com.sun.security.sasl.Provider());
            env.put("jmx.remote.profiles", "SASL/DIGEST-MD5");
            env.put(Sasl.QOP, "auth-conf");
            env.put("jmx.remote.sasl.callback.handler",
		             new DigestMD5ServerCallbackHandler("config" +
						                                    File.separator +
						                                    "password.properties",
						                                    null,
						                                    null));

            env.put("jmx.remote.x.access.file",
           		     "config" + File.separator + "access.properties");

            JMXServiceURL url = new JMXServiceURL("jmxmp", null, 5555);
            JMXConnectorServer cs =
                JMXConnectorServerFactory.newJMXConnectorServer(url, 
                                                                env, 
                                                                mbs);
            cs.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

This example is similar to the simple secure JMXMP example shown in 11.1.2 JMXMP Connectors With Simple Security. It is structured in the same way, with an environment map env being populated with the required security configurations before being passed into a new instance of JMXConnectorServer.

However, as you can see, unlike in the simple secure JMXMP example, which used the PLAIN SASL mechanism, this example uses the DIGEST-MD5 SASL mechanism. The SASL DIGEST-MD5 profile defines the digital signature that must be exchanged between the client and server for a connection to be made, based on the HTTP Digest Authentication mechanism. The HTTP Digest Authentication mechanism was developed by the Internet Engineering Task Force as RFC 2831.

With the protocol profile set to DIGEST-MD5, the level of protection to be provided is defined by the quality of protection property, Sasl.QOP. In this example, the Sasl.QOP is set to auth-conf, denoting that the types of protection to be implemented are authentication and confidentiality, namely encryption. The encryption cypher used is dictated by SASL and can be controlled by properties specific to the DIGEST-MD5 SASL mechanism.

A instance of the callback handler provided with this example, DigestMD5ServerCallbackHandler, is created with the required password file, config/password.properities, passed to it. Similarly, the name of the user allowed to connect to the server, and the level of access granted to that user, are defined when the config/access.properties file is passed into the environment map. These properties must be matched by the client end of the connector, if the connection is to succeed. In this example, the level of access rights granted is readwrite, and the approved user is called username. The password.properties file provides the password for user username that is expected by the SASL/DIGEST-MD5 profile.

The DigestMD5ServerCallbackHandler class, being an implementation of the standard Java callback interface CallbackHandler, allows the server to retrieve the authentication information it needs from the properties files described above. This example does not implement canonical naming or proxy files, so the second and third parameters passed to DigestMD5ServerCallbackHandler when it is instantiated are null. The DIGEST-MD5 server mechanism will then be able to compare them with the user credentials supplied remotely by the client.

The environment map containing all of the above is then used to create the connector server instance, cs.


Example 11–10 Implementing SASL Privacy in a JMXMP Connector Client

public class Client {

    public static void main(String[] args) {
        try {
            HshMap env = new HashMap();

            Security.addProvider(new com.sun.security.sasl.Provider());
            env.put("jmx.remote.profiles", "SASL/DIGEST-MD5");
            env.put(Sasl.QOP, "auth-conf");
            env.put("jmx.remote.sasl.callback.handler",
                    new DigestMD5ClientCallbackHandler("username", 
                                                       "password"));

            JMXServiceURL url = new JMXServiceURL("jmxmp", null, 5555);
            JMXConnector jmxc = JMXConnectorFactory.connect(url, env);

            MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();

            String domains[] = mbsc.getDomains();
            for (int i = 0; i < domains.length; i++) {
                System.out.println("\tDomain[" + i + "] = " + domains[i]);
            }

            ObjectName mbeanName = new ObjectName(
                                        "MBeans:type=SimpleStandard");
            System.out.println("\nCreate SimpleStandard MBean...");
            mbsc.createMBean("SimpleStandard", mbeanName, null, null);

            // Perform MBean operations, before unregistering MBean
            //  & closing connection
            [...]
            mbsc.unregisterMBean(mbeanName);

            jmxc.close();
            System.out.println("\nBye! Bye!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

As shown in Example 11–10 above, the client end of the private connection is created using a very similar set of properties as the server end. However, the client end of the connector supplies the user and password information via a different callback handler, DigestMD5ClientCallbackHandler. Like DigestMD5ServerCallbackHandler, DigestMD5ClientCallbackHandler is an implementation of the CallbackHandler interface. DigestMD5ClientCallbackHandler is passed the username and password expected by DigestMD5ServerCallbackHandler when it is instantiated, which it then passes to the DIGEST-MD5 client mechanism. The client DIGEST-MD5 mechanism then makes them available for comparison with the properties held by the server, thus allowing the connection to the MBean server to be established. Operations can then be performed on the MBeans the MBean server contains.

To Run the Secure JMXMP Connector Example with SASL Privacy

Run this example from within the examplesDir/current/Security/jmxmp/sasl_privacy directory.

  1. Compile the Java classes.


    $ javac -classpath classpath \
          mbeans/SimpleStandard.java \
          mbeans/SimpleStandardMBean.java \
          server/Server.java \
          server/DigestMD5ServerCallbackHandler.java \
          client/Client.java \
          client/ClientListener.java \
          client/DigestMD5ClientCallbackHandler.java 
    
  2. Start the Server.


    $ java -classpath server:mbeans:classpath Server & 
    

    You will see confirmation of the creation of the MBean server, the initialization of the environment map and the launching of the JMXMP connector and its registration in the MBean server.

  3. Start the Client.


    $ java -classpath client:mbeans:classpath Client 
    

    You will see confirmation of the creation of the JMXMP connector client, the initialization of the environment map, the connection to the MBean server and the performance of the various MBean operations followed by the closure of the connection.