JBoss Messaging Secure Socket Connection Example

$Revision: 1519 $

Overview


This example shows how to use a secure ConnectionFactory, which creates a SSL socket connection between client and server. The example will use such a ConnectionFactory to create two JMS connections: the first one to send a message to the queue and the second one to read the message from the queue. In both cases, the message will be securely sent over an encrypted connection. The example is considered successful if the client receives without any error the message that was previously sent to the queue.

This example needs to have access to a running JBoss Messaging instance. The JBoss Messaging instance must be installed and started according to the "Installation" paragraph from the release documentation. However, the example will automatically deploy its own queue, unless a queue with the same name is already deployed.

Warning

A service configuration bug that exists in all JBoss versions prior to 4.0.4.RC1 prevents this example from working correctly. You shouldn't attempt to run this example with JBoss 4.0.3.SP1 or lower, unless the patch corresponding to the JIRA issue http://jira.jboss.org/jira/browse/JBAS-1709 was applied to your installation. The bug has been fixed since JBoss 4.0.4.RC1.

This example also needs to have access to jboss-messaging-client.jar archive that comes with the release bundle. If you run this example from an unzipped installation bundle, the example run script is correctly configured to find the client jar. Otherwise, you must modify example's build.xml accordingly.


Running the example

1. Set up the JBOSS_HOME environment variable to point to the JBoss instance you deployed JBoss Messaging into. For example, if you deployed JBoss Messaging in C:\jboss-4.0.4.GA\server\messaging\deploy, then your JBOSS_HOME value should be C:\jboss-4.0.4.GA

2. Go to the example's home directory



   cd ...\examples\secure-socket


3. Run the example:



   ant



The output of a successful run should be similar to:


$ ant
Buildfile: build.xml

identify:
     [echo] ############################################################################
     [echo] #                   Running the SECURE SOCKET example                      #
     [echo] ############################################################################
     [echo] The queue: testQueue

sanity-check:

init:
    [mkdir] Created dir: C:\work\src\cvs\jboss-head\jms\docs\examples\secure-socket\output
    [mkdir] Created dir: C:\work\src\cvs\jboss-head\jms\docs\examples\common\output

compile:
    [javac] Compiling 2 source files to C:\work\src\cvs\jboss-head\jms\docs\examples\common\output
    [javac] Compiling 1 source file to C:\work\src\cvs\jboss-head\jms\docs\examples\secure-socket\output

deploy:
     [copy] Copying 1 file to C:\jboss-4.0.4.GA\server\messaging\deploy\jboss-messaging.sar
     [copy] Copying 1 file to C:\jboss-4.0.4.GA\server\messaging\deploy

sleep:
     [echo] Sleeping for 10 seconds ...

run:
     [java] Queue /queue/testQueue exists
     [java] The message was successfully sent to the testQueue queue
     [java] Received message: Hello!
     [java] The example connected to JBoss Messaging version 1.0.1.GA (1.0)

     [java] #####################
     [java] ###    SUCCESS!   ###
     [java] #####################

BUILD SUCCESSFUL
Total time: 15 seconds




Configuration details


The example client looks up a specially-configured connection factory ("/SecureConnectionFactory") that is deployed by the example run script. The secure ConnectionFactory relies on a "secured" Remoting Connector to provide the SSL connection. The definition of the required services is specified in the etc/messaging-secure-socket-service.xml deployment descriptor. The deployment descriptor, as used by the example, is listed below. Note that all services (the Connector, the secure ConnectionFactory, the SSLServerSocketFactoryService and the SSLSocketBuilder) are deployed in the same class loading domain as the messaging server:




<?xml version="1.0" encoding="UTF-8"?>

<!--
     Secure Socket Transport Example: the deployment descriptor for the secure socket factory
     service, secure connector and secure connection factory.

     $Id: remoting-service.xml,v 1.2 2006/05/08 21:35:35 ovidiu Exp $
 -->

<server>

   <loader-repository>jboss.messaging:loader=ScopedLoaderRepository
       <loader-repository-config>java2ParentDelegation=false</loader-repository-config>
   </loader-repository>

   <mbean code="org.jboss.remoting.transport.Connector"
          name="jboss.messaging:service=Connector,transport=SSLSocket"
          display-name="SSL Socket Transport Connector">
      <attribute name="Configuration">
         <config>
            <invoker transport="sslsocket">
               <attribute name="marshaller"
                          isParam="true">org.jboss.jms.server.remoting.JMSWireFormat</attribute>
               <attribute name="unmarshaller"
                          isParam="true">org.jboss.jms.server.remoting.JMSWireFormat</attribute>
               <attribute name="serializationtype" isParam="true">jboss</attribute>
               <attribute name="dataType" isParam="true">jms</attribute>
               <attribute name="socket.check_connection" isParam="true">false</attribute>
               <attribute name="timeout">0</attribute>
               <attribute name="serverBindAddress">${jboss.bind.address}</attribute>
               <attribute name="serverBindPort">5457</attribute>
               <attribute name="leasePeriod">20000</attribute>
               <attribute name="serverSocketFactory">
                          jboss.messaging:service=ServerSocketFactory,type=SSL
               </attribute>
            </invoker>
            <handlers>
               <handler subsystem="JMS">
                        org.jboss.jms.server.remoting.JMSServerInvocationHandler</handler>
            </handlers>
         </config>
      </attribute>
      <depends>jboss.messaging:service=ServerSocketFactory,type=SSL</depends>
   </mbean>

   <mbean code="org.jboss.jms.server.connectionfactory.ConnectionFactory"
      name="jboss.messaging.destination:service=SecureConnectionFactory"
      xmbean-dd="xmdesc/ConnectionFactory-xmbean.xml">
      <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
      <depends optional-attribute-name="Connector">
               jboss.messaging:service=Connector,transport=SSLSocket
      </depends>
      <attribute name="JNDIBindings">
         <bindings>
            <binding>/SecureConnectionFactory</binding>
         </bindings>
      </attribute>
   </mbean>

   <!-- This section is for custom (SSL) server socket factory  -->

   <!--
        The server socket factory mbean to be used as attribute to socket invoker (see
        serverSocketFactory attribute above for where it is used). This service provides the exact
        same API as the ServerSocketFactory, so can be set as an attribute of that type on any
        MBean requiring an ServerSocketFactory.
   -->
   <mbean code="org.jboss.remoting.security.SSLServerSocketFactoryService"
          name="jboss.messaging:service=ServerSocketFactory,type=SSL"
          display-name="SSL Server Socket Factory">
      <depends optional-attribute-name="SSLSocketBuilder"
               proxy-type="attribute">jboss.messaging:service=SocketBuilder,type=SSL</depends>
   </mbean>

   <!--
       This service is used to build the SSL Server socket factory. This will be where all the
       store/trust information will be set. If do not need to make any custom configurations,
       no extra attributes need to be set for the SSLSocketBuilder and just need to set the
       javax.net.ssl.keyStore and javax.net.ssl.keyStorePassword system properties.

       This can be done by just adding something like the following to the run script for JBoss
       (this one is for run.bat):
       set JAVA_OPTS=-Djavax.net.ssl.keyStore=.keystore
                     -Djavax.net.ssl.keyStorePassword=opensource %JAVA_OPTS%

       Otherwise, if want to customize the attributes for SSLSocketBuilder, will need to uncomment
       them below.
   -->
   <mbean code="org.jboss.remoting.security.SSLSocketBuilder"
          name="jboss.messaging:service=SocketBuilder,type=SSL"
          display-name="SSL Server Socket Factory Builder">
      <!--
           IMPORTANT - If making ANY customizations, this MUST be set to false.
           Otherwise, will used default settings and the following attributes will be ignored.
      -->
      <attribute name="UseSSLServerSocketFactory">false</attribute>
      <!-- This is the url string to the key store to use -->
      <attribute name="KeyStoreURL">messaging.keystore</attribute>
      <!-- The password for the key store -->
      <attribute name="KeyStorePassword">secureexample</attribute>
      <!-- The password for the keys (will use KeystorePassword if this is not set explicitly. -->
      <attribute name="KeyPassword">secureexample</attribute>
      <!-- The protocol for the SSLContext. Default is TLS. -->
      <attribute name="SecureSocketProtocol">TLS</attribute>
      <!-- The algorithm for the key manager factory.  Default is SunX509. -->
      <attribute name="KeyManagementAlgorithm">SunX509</attribute>
      <!--
           The type to be used for the key store.
           Defaults to JKS. Some acceptable values are JKS (Java Keystore - Sun's keystore format),
           JCEKS (Java Cryptography Extension keystore - More secure version of JKS), and
           PKCS12 (Public-Key Cryptography Standards #12 keystore - RSA's Personal Information
           Exchange Syntax Standard). These are not case sensitive.
      -->
      <attribute name="KeyStoreType">JKS</attribute>
   </mbean>

</server>



The SSLSocketBuilder needs a keystore with a public/private key pair. The example provides one (etc/messaging.keystore) which is deployed with the rest of the artifacts. In case you need to create your own keystore, this is how you do it:



 keytool -genkey -alias messaging.keypair -keyalg RSA -keystore messaging.keystore -validity 3650



By default, the client will try to contact a Certificate Authority to insure the authenticity of the public key it uses to encrypt the communication. However, the example's certificate is self-signed, so no Certificate Authority will recognize it. In order to get the SSL client to trust it and the example to complete successfully, we use a client truststore (/etc/messaging.truststore). In case you need to create your own truststore, this is how you do it:



 keytool -export -alias messaging.keypair -keystore messaging.keystore -rfc -file messaging.cer
keytool -import -alias messaging.keypair -file messaging.cer -keystore messaging.truststore


In order for the truststore to be recognized, the client's environment must contain the javax.net.ssl.trustStore and javax.net.ssl.trustStorePassword properties.


Troubleshooting

1. I get "javax.jms.JMSSecurityException: User null is NOT authenticated"

You probably didn't install JBoss Messaging correctly. A fresh JBoss Messaging installation requires changes in the security configuration of a default JBoss instance, specifically a properly configured "messaging" security domain.  Follow the instructions from the "Installation" paragraph of the release documentation.