Using HTTP-based connectors over HTTPS

The HTTP-based connectors, namely the soap, hessian and burlap connectors, can be run over the HTTPS protocol.

The configuration of the MX4J connector is quite simple, but requires understanding of how certificates and security in general work in the Java platform.
You can find more information on the security in the Java platform here.

HTTP-based MX4J connectors can be run over HTTPS by adding the string "+ssl" (without quotes) to the protocol of the JMXServiceURL normally used to start the connector over the plain HTTP protocol.
For example, the JMXServiceURL to start the SOAP connector server over plain HTTP would be something like

service:jmx:soap://host:8080/jmxconnector

while the JMXServiceURL to start the SOAP connector server over HTTPS would be something like

service:jmx:soap+ssl://host:8443/jmxconnector

However, this is not enough, since running a web container over HTTPS requires a detailed configuration of the web container itself and of the keystore that contains the certificate with the public key for the SSL protocol.

Configuration of the web container

The configuration of the web container usually requires to specify a file path for the keystore, the keystore and the key passwords, and of course the HTTPS port the web container will listen to, that must match the port provided in the JMXServiceURL.

This configuration is to be specified in the environment Map passed at the moment of the creation of the JMXConnectorServer using the mx4j.tools.remote.http.HTTPConnectorServer.WEB_CONTAINER_CONFIGURATION constant as key, and a String that points to the file path of the configuration file as value.
Below there is a sample configuration file for the default web container used by MX4J, Jetty.

Example 3.21. Example Jetty configuration file to run JMXConnectorServers over HTTPS

               
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">

<Configure class="org.mortbay.jetty.Server">
  <Call name="addListener">
    <Arg>
      <New class="org.mortbay.http.SunJsseListener">
        <Set name="Port">8443</Set>
        <Set name="PoolName">P1</Set>
        <Set name="MaxIdleTimeMs">30000</Set>
        <Set name="lowResources">30</Set>
        <Set name="LowResourcePersistTimeMs">2000</Set>
        <Set name="Keystore"><SystemProperty name="jetty.home" default="."/>/mx4j.ks</Set>
        <Set name="Password">mx4jmx4j</Set>
        <Set name="KeyPassword">mx4jmx4j</Set>

        <Set name="HttpHandler">
          <New class="org.mortbay.http.handler.MsieSslHandler">
            <Set name="UserAgentSubString">MSIE 5</Set>
          </New>
        </Set>
      </New>
    </Arg>
  </Call>
</Configure>
               
            

Note that the configuration specifies the keystore file path, the keystore and the key passwords.
Jetty allows the passwords to be obfuscated; see the Jetty documentation for more details here.

Configuration of the keystore

The keystore must contain a valid certificate issued for the server host where the web container (started by the HTTP-based JMXConnectorServer) will run on.
This is normally specified in the common name part of the distinguished name of the certificate.

Furthermore, the certificate must be trusted by the client. This means that the certificate must be signed by a well-known certification authority, and that the root certification authority must be present in the trusted certificates of the Java platform on client side, normally stored in the $JAVA_HOME/jre/lib/security/cacerts file.

In the more common case of "experiments", or during development, you can create a self-signed certificate using this command:

$JAVA_HOME/bin/keytool -genkey -keyalg "RSA" -keystore mx4j.ks -storepass mx4jmx4j -dname "cn=myhost"

Replace the keystore file path and password with your choices, and replace the common name value with the host name the web container will run on.

To avoid to import this certificate in the trusted certificates of the Java platform on client side, you must specify the following system property (using either the -D syntax in the command line that starts the JVM, or calling System.setProperty in your program):

javax.net.ssl.trustStore=mx4j.ks

Replace the keystore file path with your choice.

Needless to say we don't recommend to set these java properties in your programs, nor to share the keystore between client and server. What should be done in real environments is to sign the certificate with a trusted certification authority.

Code examples

Refer to the examples bundled with the MX4J distribution, specifically the mx4j.examples.tools.remote.hessian.ssl.* files.

Example 3.22. Starting and connecting to the Hessian connector server over HTTPS

               
// Server side configuration; copy/paste the jetty configuration above into a file named
// jetty.mx4j.xml and put it in the directory from where the JVM is launched
Map serverEnv = new HashMap();
serverEnv.put(HTTPConnectorServer.WEB_CONTAINER_CONFIGURATION, "jetty.mx4j.xml");

// Note the null host: it will use the current host name, that must match the common name
// present in the certificate contained in the keystore
JMXServiceURL url = new JMXServiceURL("hessian+ssl", null, 8443, "/hessianjmx");

JMXConnectorServer cntorServer = JMXConnectorServerFactory.newJMXConnectorServer(url, serverEnv, newMBeanServer());
cntorServer.start();

// Client side configuration; specify the trusted keystore with a system property.
// NOT recommended for production environments.
System.setProperty("javax.net.ssl.trustStore", "mx4j.ks");
JMXConnector cntor = JMXConnectorFactory.connect(url);
MBeanServerConnection cntion = cntor.getMBeanServerConnection();
int count = cntion.getMBeanCount().intValue();