SSL encrypted EJB calls with JBoss AS 7
Encrypting the communication between client and server provides improved security and privacy protection for your system. This can be an important requirement by the customer, especially if client or server need to work in an unprotected network.
This article shows you how to setup SSL encrypted EJB calls in JBoss AS 7.
Server
There are only two things that need to be done on server side:
- creating a key store with the privat/public pair of keys for the encryption and
- referencing the key store in the server configuration.
The source code of your application stays the same with or without encryption.
Creating the keys
Java provides the tool keytool which we will use to manage the key store and to create the private/public pair of keys. The example below creates a pair of 1024 bit keys using the RSA algorithm and adds them to the key store server.keystore. The key store will be created if it does not exist.
keytool -genkey -alias jboss -keyalg RSA -keysize 1024 -keystore server.keystore -validity 365 -keypass 123456 -storepass 123456 -dname "CN=localhost, O=thoughts-on-java.org"
We will need to provide this key store to the JBoss application server. Therefore I prefer to store it in the JBoss configuration directory. But you can store it where ever you want as long as the JBoss server can access it.
Server configuration
Now we have to reference the keystore in the JBoss configuration. Therefore we add a server-identities element to the security realm configuration of the application realm.
The following snippet shows an example configuration using the standard ApplicationRealm configuration and a server.keystore file located in the JBoss configuration directory:
<management> <security-realms> <security-realm name="ManagementRealm"> <authentication> <properties path="mgmt-users.properties" relative-to="jboss.server.config.dir"/> </authentication> </security-realm> <security-realm name="ApplicationRealm"> <server-identities> <ssl> <keystore path="server.keystore" relative-to="jboss.server.config.dir" password="123456"/> </ssl> </server-identities> <authentication> <properties path="application-users.properties" relative-to="jboss.server.config.dir"/> </authentication> </security-realm> </security-realms> ...
This is all that’s needs to be done on server side.
Client
On client side, we need to do the following things:
- import the public key of the server into the client key store,
- define SSL encryption in the EJBClientProperties and
- provide the location and password of a key store with the public key JVM arguments.
Importing the key
First we need to export the public key of the key pair we added to the server key store. This can be done with the keytool, too:
keytool -export -keystore server.keystore -alias jboss -file server.cer -keypass 123456 -storepass 123456
The key store will be created if it does not exist.
OK, now we can add the key to the client keystore:
keytool -import -trustcacerts -alias jboss -file server.cer -keystore client.keystore -keypass 123456 -storepass 123456
EJBClientProperties
There is no big difference in the EJBClientProperties. The properties remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED and remote.connection.default.connect.options.org.xnio.Options.SSL_STARTTLS need to be set to true. The rest stays unchanged.
The following snippet shows the creation of an SSL encrypted connection to the server and the lookup of an SLSB.
// define EJB client properties final Properties props = new Properties(); // define SSL encryption props.put("remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED", "true"); props.put("remote.connection.default.connect.options.org.xnio.Options.SSL_STARTTLS", "true"); // connection properties props.put("remote.connections", "default"); props.put("remote.connection.default.host", "localhost"); props.put("remote.connection.default.port", "4447"); // user credentials props.put("remote.connection.default.username", "test"); props.put("remote.connection.default.password", "1234"); props.put("remote.connection.default.connect.options.org.xnio.Options.SASL_DISALLOWED_MECHANISMS", "JBOSS-LOCAL-USER"); props.put("remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT", "false"); props.put("remote.connection.default.connect.options.org.jboss.remoting3.RemotingOptions.HEARTBEAT_INTERVAL", "600000"); // create EJB client configuration final EJBClientConfiguration clientConfiguration = new PropertiesBasedEJBClientConfiguration( props); // create and set a context selector final ContextSelector<EJBClientContext> contextSelector = new ConfigBasedEJBClientContextSelector( clientConfiguration); EJBClientContext.setSelector(contextSelector); // create InitialContext final Hashtable<Object, Object> contextProperties = new Hashtable<>(); ejbURLContextFactory.class.getName(); contextProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming"); InitialContext initialContext = new InitialContext(contextProperties); // lookup SLSB GreeterRemote greeter = (GreeterRemote) initialContext .lookup("ejb:/test/Greeter!blog.thoughts.on.java.ssl.remote.GreeterRemote"); Assert.assertEquals("Hello World!", greeter.greet("World"));
JVM arguments
OK, now we are nearly done. The only thing missing is the reference to the client key store. This can be done with the JVM arguments javax.net.ssl.trustStore for the location and javax.net.ssl.trustStorePassword for the password of the key store, e.g.:
-Djavax.net.ssl.trustStore=src\test\resources\client.keystore -Djavax.net.ssl.trustStorePassword=123456
This is all needs to be done to setup SSL encrypted EJB calls with JBoss AS 7.
Troubleshooting
If there are any communication problems, you can set -Djavax.net.debug=true to enable debug messages.
Conclusion
In this article we had a look at the configuration and code changes to setup encrypted EJB calls with JBoss AS 7. It can be done in a few minutes and provides an improved security and privacy protection to your communication.
Reference: | SSL encrypted EJB calls with JBoss AS 7 from our JCG partner Thorben Janssen at the Some thoughts on Java (EE) blog. |