JBoss.orgCommunity Documentation
JBoss Application Server uses a socket-based invoker layer for Remote Method Invocation (RMI) of EJB2 and EJB3 Beans. This network traffic is not encrypted by default. Follow the instructions in this chapter to use Secure Sockets Layer (SSL) to encrypt this network traffic.
Procedure 12.1. Configure SSL for EJB3 Overview
Generate encryption keys and certificate
Configure a secure remote connector
Annotate EJB3 beans that will use the secure connector
Procedure 12.2. Configure SSL for EJB2 Overview
Generate encryption keys and certificate
Configure Unified Invoker for SSL
Secure Sockets Layer (SSL) encrypts network traffic between two systems. Traffic between the two systems is encrypted using a two-way key, generated during the handshake phase of the connection and known only by those two systems.
For secure exchange of the two-way encryption key, SSL makes use of Public Key Infrastructure (PKI), a method of encryption that utilizes a key pair. A key pair consists of two separate but matching cryptographic keys - a public key and a private key. The public key is shared with others and is used to encrypt data, and the private key is kept secret and is used to decrypt data that has been encrypted using the public key. When a client requests a secure connection a handshake phase takes place before secure communication can begin. During the SSL handshake the server passes its public key to the client in the form of a certificate. The certificate contains the identity of the server (its URL), the public key of the server, and a digital signature that validates the certificate. The client then validates the certificate and makes a decision about whether the certificate is trusted or not. If the certificate is trusted, the client generates the two-way encryption key for the SSL connection, encrypts it using the public key of the server, and sends it back to the server. The server decrypts the two-way encryption key, using its private key, and further communication between the two machines over this connection is encrypted using the two-way encryption key.
On the server, public/private key pairs are stored in a key store, an encrypted file that stores key pairs and trusted certificates. Each key pair within the key store is identified by an alias - a unique name that is used when storing or requesting a key pair from the key store. The public key is distributed to clients in the form of a certificate, a digital signature which binds together a public key and an identity. On the client, certificates of known validity are kept in the default key store known as a trust store.
Public Key Infrastructure relies on a chain of trust to establish the credentials of unknown machines. The use of public keys not only encrypts traffic between machines, but also functions to establish the identity of the machine at the other end of a network connection. A "Web of Trust" is used to verify the identity of servers. A server may be unknown to you, but if its public key is signed by someone that you trust, you extend that trust to the server. Certificate Authorities are commercial entities who verify the identity of customers and issue them signed certificates. The JDK includes a cacerts
file with the certificates of several trusted Certificate Authorities (CAs). Any keys signed by these CAs will be automatically trusted. Large organizations may have their own internal Certificate Authority, for example using Red Hat Certificate System. In this case the signing certificate of the internal Certificate Authority is typically installed on clients as part of a Corporate Standard Build, and then all certificates signed with that certificate are trusted. CA-signed certificates are best practice for production scenarios.
During development and testing, or for small-scale or internal-only production scenarios, you may use a self-signed certificate. This is certificate that is not signed by a Certificate Authority, but rather with a locally generated certificate. Since a locally generated certificate is not in the cacerts
file of clients, you need to export a certificate for that key on the server, and import that certificate on any client that will connect via SSL.
The JDK includes keytool
, a command line tool for generating key pairs and certificates. The certificates generated by keytool
can be sent for signing by a CA or can be distributed to clients as a self-signed certificate.
Generating a self-signed certificate for development use and importing that certificate to a client is described in Section 12.2.1, “Generate a self-signed certificate with keytool”.
Generating a certificate and having it signed by a CA for production use is beyond the scope of this edition. Refer to the manpage for keytool for further information on performing this task.
The keytool command, part of the JDK, is used to generate a new key pair. Keytool can either add the new key pair to an existing key store, or create a new key store at the same time as the key pair.
This key pair will be used to negotiate SSL encryption between the server and remote clients. The following procedure generates a key pair and stores it in a key store called localhost.keystore
. You will need to make this key store available to the EJB3 invoker on the server. The key pair in our example will be saved in the key store under the alias 'ejb-ssl'. We will need this key alias, and the key pair password you supply (if any), when configuring the EJB3 Remoting connector in Section 12.3.1, “Create a secure remoting connector for EJB3”.
Procedure 12.3. Generate a new key pair and add it to the key store "localhost.keystore"
In your home directory, issue the following command, substituting a new password for EJB-SSL_KEYPAIR_PASSWORD
:
keytool -genkey -alias ejb-ssl -keypass EJB-SSL_KEYPAIR_PASSWORD
-keystore localhost.keystore
Enter the key store password, if this key store already exists; otherwise enter and re-enter a password for a new key store that will be created.
Issue the command:
dir
You should now see the file localhost.keystore
.
Key store files should be stored on a secure file system, and should be readable only by the owner of the JBoss Application Server process.
Note that if no key store is specified on the command line, keytool
will add the key pair to a new key store called keystore
in the current user's home directory. This key store file will be a hidden file.
Once a key pair has been generated for the server to use, a certificate must be created. Export a certificate details the steps to export the ejb-ssl
key from the key store named localhost.keystore
.
Any client machine that will make remote method invocations over SSL needs to trust the certificate of the server. Since the certificate we generated is self-signed, and has no chain of trust to a known certificate authority, the client must be explicitly configured to trust the certificate or the connection will fail. Configuring a client to trust a self-signed certificate requires importing the self-signed server certificate to a trust store on the client.
A trust store is a key store that contains trusted certificates. Certificates that are in the local trust store will be accepted as valid. If your server uses a self-signed certificate then any clients that will make remote method calls over SSL must have that certificate in their trust store. You must export your public key as a certificate, and then import that certificate to the trust store on those clients.
The certificate created in Section 12.2.1.2, “Export a self-signed certificate” must be copied to the client in order to perform the steps detailed in Import the certificate to the trust store "localhost.truststore".
Procedure 12.5. Import the certificate to the trust store "localhost.truststore"
Issue the following command on the client:
keytool -import -alias ejb-ssl -file mycert.cer -keystore localhost.truststore
Enter the password for this trust store if it already exists; otherwise enter and re-enter the password for the trust store that will be created.
Verify the details of the certificate, and if it is the correct one, type 'yes' to import it to the trust store.
The certificate will be imported to the trust store, and you will be able to establish a secure connection with a server that uses this certificate.
As with the key store, if the trust store specified does not already exist, it will be created. However, in contrast with the key store, there is no default trust store, and one must be specified.
Now that you have imported the self-signed server certificate to a trust store on the client, you must instruct the client to use this trust store. This is done by passing the localhost.truststore
location to the application using the javax.net.ssl.trustStore
property, and the trust store password using the javax.net.ssl.trustStorePassword
property. Example 12.1, “Invoking the com.acme.Runclient application with a specific trust store” is an example commandline that would be used to invoke the application com.acme.RunClient, which will make remote method calls to an EJB on a JBoss Application Server.
Example 12.1. Invoking the com.acme.Runclient application with a specific trust store
java -Djavax.net.ssl.trustStore=${resources}/localhost.truststore \
-Djavax.net.ssl.trustStorePassword=TRUSTSTORE_PASSWORD
com.acme.RunClient
The file ejb3-connectors-jboss-beans.xml
in a JBoss Application Server profile's deploy
directory contains JBoss Remoting connector definitions for EJB3 remote method invocation. Example 12.2, “Sample Secure EJB3 Connector” is a sample configuration that defines a secure connector for EJB3 using the key pair created in Generate a new key pair and add it to the key store "localhost.keystore". The keyPassword
property in the sample configuration is the key pair password that was specified when the key pair was created.
Example 12.2. Sample Secure EJB3 Connector
<bean name="EJB3SSLRemotingConnector" class="org.jboss.remoting.transport.Connector"> <property name="invokerLocator">sslsocket://${jboss.bind.address}:3843</property> <property name="serverConfiguration"> <inject bean="ServerConfiguration" /> </property> <property name="serverSocketFactory"> <inject bean="sslServerSocketFactory" /> </property> </bean> <bean name="sslServerSocketFactory" class="org.jboss.security.ssl.DomainServerSocketFactory"> <constructor> <parameter><inject bean="EJB3SSLDomain"/></parameter> </constructor> </bean> <bean name="EJB3SSLDomain" class="org.jboss.security.plugins.JaasSecurityDomain"> <constructor> <parameter>EJB3SSLDomain</parameter> </constructor> <property name="keyStoreURL">resource:localhost.keystore</property> <property name="keyStorePass">KEYSTORE_PASSWORD</property> <property name="keyAlias">ejb-ssl</property> <property name="keyPassword">EJB-SSL_KEYPAIR_PASSWORD</property> </bean>
The sample configuration will create a connector that listens for SSL connections on port 3843. This port will need to be opened on the server firewall for access by clients.
All EJB3 beans use the unsecured RMI connector by default. In order to enabled a bean to be invoked via SSL, the bean needs to be annotated with @org.jboss.annotation.ejb.RemoteBinding
.
The annotation in Example 12.3, “EJB3 bean annotation to enable secure remote invocation” will bind an EJB3 bean to the JNDI name StatefulSSL
. The proxy implementing the remote interface, returned to a client when the bean is requested from JNDI, will communicate with the server via SSL.
Example 12.3. EJB3 bean annotation to enable secure remote invocation
@RemoteBinding(clientBindUrl="sslsocket://0.0.0.0:3843", jndiBinding="StatefulSSL"), @Remote(BusinessInterface.class) public class StatefulBean implements BusinessInterface { ... }
In Example 12.3, “EJB3 bean annotation to enable secure remote invocation” the IP address is specified as 0.0.0.0, meaning "all interfaces". This should be changed in practice to the value of the ${jboss.bind.address} system property.
You can enable both secure and insecure remote method invocation of the same EJB3 bean. Example 12.4, “EJB3 Bean annotation for both secure and insecure remote invocation” demonstrates the annotations to do this.
Example 12.4. EJB3 Bean annotation for both secure and insecure remote invocation
@RemoteBindings({ @RemoteBinding(clientBindUrl="sslsocket://0.0.0.0:3843", jndiBinding="StatefulSSL"), @RemoteBinding(jndiBinding="StatefulNormal") }) @Remote(BusinessInterface.class) public class StatefulBean implements BusinessInterface { ... }
If a client requests StatefulNormal
from JNDI, the returned proxy implementing the remote interface will communicate with the server via the unencrypted socket protocol; and if StatefulSSL
is requested, the returned proxy implementing the remote interface will communicate with the server via SSL.
EJB2 remote invocation uses a single unified invoker, which runs by default on port 4446. The configuration of the unified invoker used for EJB2 remote method invocation is defined in the deploy/remoting-jboss-beans.xml
file of a JBoss Application Server profile. Add the following SSL Socket Factory bean and an SSL Domain bean in this file.
Example 12.5. SSL Server Factory for EJB2
<bean name="sslServerSocketFactoryEJB2" class="org.jboss.security.ssl.DomainServerSocketFactory"> <constructor> <parameter><inject bean="EJB2SSLDomain"/></parameter> </constructor> </bean> <bean name="EJB2SSLDomain" class="org.jboss.security.plugins.JaasSecurityDomain"> <constructor> <parameter>EJB2SSLDomain</parameter> </constructor> <property name="keyStoreURL">resource:localhost.keystore</property> <property name="keyStorePass">changeit</property> <property name="keyAlias">ejb-ssl</property> <property name="keyPassword">EJB-SSL_KEYPAIR_PASSWORD</property> </bean>
In the deploy/remoting-jboss-beans.xml
file in the JBoss Application Server profile, update the code to reflect the information below:
Example 12.6. SSL Transport for Beans
... <bean name="UnifiedInvokerConnector" class="org.jboss.remoting.transport.Connector"> <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.remoting:service=Connector,transport=socket", exposedInterface=org.jboss.remoting.transport.ConnectorMBean.class,registerDirectly=true) </annotation> <property name="serverConfiguration"><inject bean="UnifiedInvokerConfiguration"/></property> <!-- add this to configure the SSL socket for the UnifiedInvoker --> <property name="serverSocketFactory"><inject bean="sslServerSocketFactoryEJB2"/></property> </bean> ... <bean name="UnifiedInvokerConfiguration" class="org.jboss.remoting.ServerConfiguration"> <constructor> <!-- transport: Others include sslsocket, bisocket, sslbisocket, http, https, rmi, sslrmi, servlet, sslservlet. --> <parameter>sslsocket</parameter><!-- changed from socket to sslsocket --> </constructor> ... </bean> ...