10.8. Using SSL with JBoss

10.8.1. Adding SSL to EJB3

By default JBoss EJB3 uses a socket based invoker layer on port 3878. This is set up in $JBOSS_HOME/server/<serverconfig>/deploy/ejb3.deployer/META-INF/jboss-service.xml. In some cases you may wish to use SSL as the protocol. In order to do this you must generate a keystore and then configure your beans to use SSL transport.

10.8.1.1. Generating the keystore and truststore

For SSL to work you need to create a public/private key pair, which will be stored in a keystore. Generate this using the genkey command that comes with the JDK.
 $cd $JBOSS_HOME/server/production/conf/
 $keytool -genkey -alias ejb3-ssl -keypass opensource -keystore localhost.keystore
   Enter keystore password:  opensource
   What is your first and last name?
     [Unknown]:
   What is the name of your organizational unit?
     [Unknown]:
   What is the name of your organization?
     [Unknown]:
   What is the name of your City or Locality?
     [Unknown]:
   What is the name of your State or Province?
     [Unknown]:
   What is the two-letter country code for this unit?
     [Unknown]:
   Is CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown correct?
     [no]:  yes
where alias is the name ("ejb2-ssl") of the key pair within the keystore. keypass is the password ("opensource") for the keystore, and keystore specifies the location ("localhost.keystore") of the keystore to create/add to.
Since you have not signed our certificate through any certification authoritiy, you also need to create a truststore for the client, explicitly saying that you trust the certificate you just created. The first step is to export the certificate using the JDK keytool:
   $ keytool -export -alias ejb3-ssl -file mycert.cer -keystore localhost.keystore
   Enter keystore password:  opensource
   Certificate stored in file <mycert.cer>
Then you need to create the truststore if it does not exist and import the certificate into the trueststore:
   $ keytool -import -alias ejb3-ssl -file mycert.cer -keystore localhost.truststore
   Enter keystore password:  opensource
   Owner: CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
   Issuer: CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
   Serial number: 43bff927
   Valid from: Sat Jan 07 18:23:51 CET 2006 until: Fri Apr 07 19:23:51 CEST 2006
   Certificate fingerprints:
            MD5:  CF:DC:71:A8:F4:EA:8F:5A:E9:94:E3:E6:5B:A9:C8:F3
            SHA1: 0E:AD:F3:D6:41:5E:F6:84:9A:D1:54:3D:DE:A9:B2:01:28:F6:7C:26
   Trust this certificate? [no]:  yes
   Certificate was added to keystore

10.8.1.2. Setting up the SSL transport

The simplest way to define an SSL transport is to define a new Remoting connector using the sslsocket protocol as follows. This transport will listen on port 3843:
   <mbean code="org.jboss.remoting.transport.Connector"
      xmbean-dd="org/jboss/remoting/transport/Connector.xml"
      name="jboss.remoting:type=Connector,transport=socket3843,handler=ejb3">
      <depends>jboss.aop:service=AspectDeployer</depends>
      <attribute name="InvokerLocator">sslsocket://0.0.0.0:3843</attribute>
      <attribute name="Configuration">
         <handlers>
            <handler subsystem="AOP">
             org.jboss.aspects.remoting.AOPRemotingInvocationHandler
            </handler>
         </handlers>
      </attribute>
   </mbean>
Now you need to tell JBoss Remoting where to find the keystore to be used for SSl and its password. This is done using javax.net.ssl.keyStore and javax.net.ssl.keyStorePassword=opensource system properties when starting JBoss, as the following example shows:
  $cd $JBOSS_HOME/bin
  $ run -Djavax.net.ssl.keyStore=../server/production/conf/localhost.keystore 
          -Djavax.net.ssl.keyStorePassword=opensource

10.8.1.3. Configuring your beans to use the SSL transport

By default all the beans will use the default connector on socket://0.0.0.0:3873. By using the @org.jboss.annotation.ejb.RemoteBinding annotation you can have the bean invokable via SSL.
 @RemoteBinding(clientBindUrl="sslsocket://0.0.0.0:3843", jndiBinding="StatefulSSL"),
   @Remote(BusinessInterface.class)
   public class StatefulBean implements BusinessInterface
   {
      ...
   }
This bean will be bound under the JNDI name StatefulSSL and the proxy implementing the remote interface returned to the client will communicate with the server via SSL.
You can also enable different types of communication for your beans
 @RemoteBindings({
      @RemoteBinding(clientBindUrl="sslsocket://0.0.0.0:3843", jndiBinding="StatefulSSL"),
      @RemoteBinding(jndiBinding="StatefulNormal")
   })
   @Remote(BusinessInterface.class)
   public class StatefulBean implements BusinessInterface
   {
      ...
   }
Now if you look up StatefulNormal the returned proxy implementing the remote interface will communicate with the server via the normal unencrypted socket protocol, and if you look up StatefulSSL the returned proxy implementing the remote interface will communicate with the server via SSL.

10.8.1.4. Setting up the client to use the truststore

If not using a certificate signed by a certificate authorization authority, you need to point the client to the truststore using the javax.net.ssl.trustStore system property and specify the password using the javax.net.ssl.trustStorePassword system property:
java -Djavax.net.ssl.trustStore=${resources}/test/ssl/localhost.truststore
 -Djavax.net.ssl.trustStorePassword=opensource com.acme.RunClient