I’ve been struggling with configuring a password protected Resin-deployed JMX application on windows recently. This is being blogged in the hope that Google will pick this up and make the process much simpler for someone later on.

These instructions assume you are using Resin, but should work for any container.

h3. Enabling Password Protection

Starting Resin secured using a password is pretty simple. Firstly, start Resin with the following properties:

com.sun.management.jmxremote.port=
com.sun.management.jmxremote.authenticate=true
com.sun.management.jmxremote.ssl=false
com.sun.management.jmxremote.password.file=
com.sun.management.jmxremote.access.file=

Next, you’ll need to create @jmx.access@ file, like so:

joeblogs readwrite

And a @jmx.passwd@:

joeblogs password1

p. jmx.passwd needs to be secured such that only the user running the Resin process can access the file. On Linux or Unix, this is simply a case of running @chmod 400 jmx.passwd@. However on Windows this is more involved – the “five step process(How to a Secure Password File on Microsoft Windows Systems)”:http://java.sun.com/j2se/1.5.0/docs/guide/management/security-windows.html required to secure the file is rather baroque, and worst of all makes running JMX applications secured in this manner rather hard for development teams, as this has to be done each time the file is checked out. I suspect a “Calcs”:http://www.ss64.com/nt/cacls.html or “SetAcl”:http://setacl.sourceforge.net/ script could be folded into the build, but it really shouldn’t be that hard. I suspect Sun want us all to use SSL instead.

h3. Programatically working with password protected JMX

This “sample from sun”:http://java.sun.com/j2se/1.5.0/docs/guide/jmx/examples/Security/simple/client/Client.java shows how to work with your newly password-protected JMX app:

public class Client {

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

      String[] credentials = new String[] { "username" , "password" };
      env.put("jmx.remote.credentials", credentials);
      JMXServiceURL url = new JMXServiceURL(
         "service:jmx:rmi:///jndi/rmi://localhost:9999/server");
      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("Domain[" + i + "] = " + domains[i]);
      }

      ObjectName mbeanName =
          new ObjectName("MBeans:type=SimpleStandard");
      mbsc.createMBean("SimpleStandard", mbeanName, null, null);
      // Perform MBean operations
      [...]

      mbsc.unregisterMBean(mbeanName);
      jmxc.close();
    }  catch (Exception e) {
      e.printStackTrace();
    }
  }
}
Advertisements