JBoss.org Community Documentation

8.8. Using SSL with JBoss using JSSE

JBoss uses JSEE, the Java Secure Socket Extension (JSSE), for SSL. JSSE is bundled with JDK 1.4. To get started with JSSE you need a public key/private key pair in the form of an X509 certificate for use by the SSL server sockets. For the purpose of this example we have created a self-signed certificate using the JDK keytool and included the resulting keystore file, example.keystore. It was created using the following command and input:

 keytool -genkey -keystore example.keystore -storepass rmi+ssl -keypass rmi+ssl -keyalg RSA -alias example -validity 3650 -dname "cn=example,ou=admin book,dc=jboss,dc=org"

This produces a keystore file called example.keystore. A keystore is a database of security keys. There are two different types of entries in a keystore:

  • key entries : each entry holds very sensitive cryptographic key information, which is stored in a protected format to prevent unauthorized access. Typically, a key stored in this type of entry is a secret key, or a private key accompanied by the certificate chain for the corresponding public key. The keytool and jarsigner tools only handle the later type of entry, that is private keys and their associated certificate chains.

  • trusted certificate entries : each entry contains a single public key certificate belonging to another party. It is called a trusted certificate because the keystore owner trusts that the public key in the certificate indeed belongs to the identity identified by the subject (owner) of the certificate. The issuer of the certificate vouches for this, by signing the certificate.

Listing the src/main/org/jboss/book/security/example.keystore examples file contents using the keytool shows one self-signed certificate:

[examples]$ keytool -list -v -keystore src/main/org/jboss/book/security/example.keystore
Enter keystore password:  rmi+ssl

Keystore type: jks
Keystore provider: SUN

Your keystore contains 1 entry

Alias name: example
Creation date: Oct 31, 2006
Entry type: keyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=example, OU=admin book, DC=jboss, DC=org
Issuer: CN=example, OU=admin book, DC=jboss, DC=org
Serial number: 45481c1b
Valid from: Tue Oct 31 22:01:31 CST 2006 until: Fri Oct 28 23:01:31 CDT 2016
Certificate fingerprints:
         MD5:  C2:CA:CA:D3:00:71:3E:32:CB:B3:C8:A8:4E:68:9A:BB
         SHA1: A6:44:EF:66:2A:49:14:B0:A4:14:74:8B:64:61:E4:E6:AF:E3:70:41


*******************************************
*******************************************

With JSSE working and a keystore with the certificate you will use for the JBoss server, your are ready to configure JBoss to use SSL for EJB access. This is done by configuring the EJB invoker RMI socket factories. The JBossSX framework includes implementations of the java.rmi.server.RMIServerSocketFactory and java.rmi.server.RMIClientSocketFactory interfaces that enable the use of RMI over SSL encrypted sockets. The implementation classes are org.jboss.security.ssl.RMISSLServerSocketFactory and org.jboss.security.ssl.RMISSLClientSocketFactory respectively. There are two steps to enable the use of SSL for RMI access to EJBs. The first is to enable the use of a keystore as the database for the SSL server certificate, which is done by configuring an org.jboss.security.plugins.JaasSecurityDomain MBean. The jboss-service.xml descriptor in the book/security/ex4 directory includes the JaasSecurityDomain definition shown in Example 8.14, “A sample JaasSecurityDomain config for RMI/SSL”.

<!-- The SSL domain setup -->
<mbean code="org.jboss.security.plugins.JaasSecurityDomain"
       name="jboss.security:service=JaasSecurityDomain,domain=RMI+SSL">
    <constructor>
        <arg type="java.lang.String" value="RMI+SSL"/>
    </constructor>
    <attribute name="KeyStoreURL">example.keystore</attribute>
    <attribute name="KeyStorePass">rmi+ssl</attribute>
</mbean> 

Example 8.14. A sample JaasSecurityDomain config for RMI/SSL


The JaasSecurityDomain is a subclass of the standard JaasSecurityManager class that adds the notions of a keystore as well JSSE KeyManagerFactory and TrustManagerFactory access. It extends the basic security manager to allow support for SSL and other cryptographic operations that require security keys. This configuration simply loads the example.keystore from the example 4 MBean SAR using the indicated password.

The second step is to define an EJB invoker configuration that uses the JBossSX RMI socket factories that support SSL. To do this you need to define a custom configuration for the JRMPInvoker we saw in Chapter 11, EJBs on JBoss as well as an EJB setup that makes use of this invoker. The top of the listing shows the jboss-service.xml descriptor that defines the custom JRMPInovker

<mbean code="org.jboss.invocation.jrmp.server.JRMPInvoker"
       name="jboss:service=invoker,type=jrmp,socketType=SSL">
    <attribute name="RMIObjectPort">14445</attribute>
    <attribute name="RMIClientSocketFactory"> 
        org.jboss.security.ssl.RMISSLClientSocketFactory
    </attribute>
    <attribute name="RMIServerSocketFactory">
        org.jboss.security.ssl.RMISSLServerSocketFactory
    </attribute>
    <attribute name="SecurityDomain">java:/jaas/RMI+SSL</attribute>
    <depends>jboss.security:service=JaasSecurityDomain,domain=RMI+SSL</depends>
</mbean>

To set up an SSL invoker, we will create an invoker binding named stateless-ssl-invoker that uses our custom JRMPInvoker. We can declare the invoker binding and connect it to EchoBean4 as shown in the following jboss.xml file.

<?xml version="1.0"?>
<jboss>
    <enterprise-beans>
        <session>
            <ejb-name>EchoBean4</ejb-name>
            <configuration-name>Standard Stateless SessionBean</configuration-name>
            <invoker-bindings>
                <invoker>
                    <invoker-proxy-binding-name>
                        stateless-ssl-invoker
                    </invoker-proxy-binding-name>
                </invoker>
            </invoker-bindings>
        </session>
    </enterprise-beans>
    
    <invoker-proxy-bindings>
        <invoker-proxy-binding>
            <name>stateless-ssl-invoker</name>
            <invoker-mbean>jboss:service=invoker,type=jrmp,socketType=SSL</invoker-mbean>
            <proxy-factory>org.jboss.proxy.ejb.ProxyFactory</proxy-factory>
            <proxy-factory-config>
            <client-interceptors>
                <home>
                    <interceptor>org.jboss.proxy.ejb.HomeInterceptor</interceptor>
                    <interceptor>org.jboss.proxy.SecurityInterceptor</interceptor>
                    <interceptor>org.jboss.proxy.TransactionInterceptor</interceptor>
                    <interceptor>org.jboss.invocation.InvokerInterceptor</interceptor>
                </home>
                <bean>
                    <interceptor>org.jboss.proxy.ejb.StatelessSessionInterceptor</interceptor>
                    <interceptor>org.jboss.proxy.SecurityInterceptor</interceptor>
                    <interceptor>org.jboss.proxy.TransactionInterceptor</interceptor>
                    <interceptor>org.jboss.invocation.InvokerInterceptor</interceptor>
                </bean>
            </client-interceptors>
            </proxy-factory-config>
        </invoker-proxy-binding>
    </invoker-proxy-bindings>
</jboss>

The example 4 code is located under the src/main/org/jboss/book/security/ex4 directory of the book examples. This is another simple stateless session bean with an echo method that returns its input argument. It is hard to tell when SSL is in use unless it fails, so we'll run the example 4 client in two different ways to demonstrate that the EJB deployment is in fact using SSL. Start the JBoss server using the default configuration and then run example 4b as follows:

[examples]$ ant -Dchap=security -Dex=4b run-example
...
run-example4b:
...
     [java] Exception in thread "main" java.rmi.ConnectIOException: error during JRMP connect
ion establishment; nested exception is: 
     [java]     javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorExceptio
n: No trusted certificate found
...            

The resulting exception is expected, and is the purpose of the 4b version of the example. Note that the exception stack trace has been edited to fit into the book format, so expect some difference. The key item to notice about the exception is it clearly shows you are using the Sun JSSE classes to communicate with the JBoss EJB container. The exception is saying that the self-signed certificate you are using as the JBoss server certificate cannot be validated as signed by any of the default certificate authorities. This is expected because the default certificate authority keystore that ships with the JSSE package only includes well known certificate authorities such as VeriSign, Thawte, and RSA Data Security. To get the EJB client to accept your self-signed certificate as valid, you need to tell the JSSE classes to use your example.keystore as its truststore. A truststore is just a keystore that contains public key certificates used to sign other certificates. To do this, run example 4 using -Dex=4 rather than -Dex=4b to pass the location of the correct truststore using the javax.net.ssl.trustStore system property:

[examples]$ ant -Dchap=security -Dex=4 run-example
...
run-example4:
	[copy] Copying 1 file to /tmp/jboss-4.2.0/server/production/deploy
	[echo] Waiting for 5 seconds for deploy...
...
	[java] Created Echo
	[java] Echo.echo()#1 = This is call 1

This time the only indication that an SSL socket is involved is because of the SSL handshakeCompleted message. This is coming from the RMISSLClientSocketFactory class as a debug level log message. If you did not have the client configured to print out log4j debug level messages, there would be no direct indication that SSL was involved. If you note the run times and the load on your system CPU, there definitely is a difference. SSL, like SRP, involves the use of cryptographically strong random numbers that take time to seed the first time they are used. This shows up as high CPU utilization and start up times.

One consequence of this is that if you are running on a system that is slower than the one used to run the examples for the book, such as when running example 4b, you may seen an exception similar to the following:

javax.naming.NameNotFoundException: EchoBean4 not bound
   at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer
...

The problem is that the JBoss server has not finished deploying the example EJB in the time the client allowed. This is due to the initial setup time of the secure random number generator used by the SSL server socket. If you see this issue, simply rerun the example again or increase the deployment wait time in the build-security.xml Ant script.