Securing a JMS bridge between Weblogic and HornetQ

I posted my notes about setting up a JMS bridge between Weblogic and HornetQ last September, now I’d like to talk about how to secure the connection: implementing an user authentication & authorization process and ensuring the communication between the servers with SSL. Finally, I’ll write about accessing to the secured queue from a Message Driven Bean (MDB) deployed on JBoss 6.1.  Most of the configuration is made on HornetQ, therefore I’ll make references to its User Manual.

The first step was to set up a security constraint, in order to ensure that just the user assigned to Weblogic 10.3 for the bridge could access to the queue of HornetQ. I had previously created a security role (testRole) and a user (testUser) belonging to it on JBoss, the procedure to do this may be different, depending on the security manager you’re using, and it’s out of the scope of this post. I used the defaults for testing purposes and just had to write a line in the files %JBOSS_HOME%\server\default\conf\props\hornetq-users.properties and %JBOSS_HOME%\server\default\conf\props\hornetq-roles.properties  Once I configured the user and the role, I edited the file %JBOSS_HOME%\ server\default\deploy\hornetq\hornetq-configuration.xml and added the following security setting:

<security-setting match="jms.queue.TestQueue">
  <permission type="consume" roles="testRole"/>
  <permission type="send" roles="testRole"/>
</security-setting>

Please, read the security chapter of the HornetQ User Manual to know about the different permissions that can be defined, addressing and wildcards.

The next step was to modify the Weblogic bridge destination on the console, in order to set up the user assigned by JBoss, here you have the excerpt from the resulting config.xml file:

<jms-bridge-destination>
  <name>JMS Bridge Destination-Target</name>
  <adapter-jndi-name>eis.jms.WLSConnectionFactoryJNDIXA</adapter-jndi-name>
  <user-name>testUser</user-name>
  <user-password-encrypted>{AES}GZTa15osrQW6/5rbE2fzm+a9BX/YPY7Hm3xiIFi0oMQ=</user-password-encrypted>
  <classpath></classpath>
  <connection-factory-jndi-name>jms/TestXAQueueConnectionFactory</connection-factory-jndi-name>
  <initial-context-factory>org.jnp.interfaces.NamingContextFactory</initial-context-factory>
  <connection-url>jnp://srvhornetq.test.local:1099</connection-url>
  <destination-jndi-name>jms/TestQueue</destination-jndi-name>
  <destination-type>Queue</destination-type>
</jms-bridge-destination>

The following issue was to secure the traffic between Weblogic and the JBoss server, where HornetQ was running as a JMS provider. To accomplish that goal, it was very useful to read the chapter about transport of the HornetQ User Manual. A previous task at this point was to prepare a self-signed certificate using keytool, the sentence I executed to create the client keystore was:

keytool -genkeypair -alias test -keyalg RSA -keysize 1024 -dname OU=TEST,CN=TEST,CN=LOCAL
        -keypass test1234 -keystore hornetq.test.keystore -storepass test1234

In order to create the trust keystore, I simply imported the client keystore into a new one:

keytool -importkeystore -srckeystore hornetq.test.keystore -destkeystore
         hornetq.test.truststore -srcstorepass test1234 -deststorepass test1234

I put these two keystores into the %JBOSS_HOME%\server\default\data\hornetq directory, so the acceptor that listens for SSL connections, could access them. I also copied the hornetq.test.keystore to the file system of Weblogic, in order to be accessed by the connector. Here you have an excerpt from the hornetq-configuration.xml file:

<connectors>
...
  <connector name="netty-ssl-connector">
    <factory-class>org.hornetq.core.remoting.impl.netty.NettyConnectorFactory</factory-class>
    <param key="host" value="${jboss.bind.address:localhost}"/>
    <param key="port" value="${hornetq.remoting.netty.port.ssl:5446}"/>
    <param key="ssl-enabled" value="true"/>
    <param key="key-store-path" value="/oracle/hornetq/hornetq/hornetq.test.keystore"/>
    <param key="key-store-password" value="test1234"/>
  </connector>
...
</connectors>

<acceptors>
...
  <acceptor name="netty-ssl-acceptor">
    <factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class>
    <param key="host" value="${jboss.bind.address:localhost}"/>
    <param key="port" value="${hornetq.remoting.netty.port.ssl:5446}"/>
    <param key="ssl-enabled" value="true"/>
    <param key="key-store-path" value="${jboss.server.data.dir}/hornetq/hornetq.test.keystore"/>
    <param key="key-store-password" value="test1234"/>
    <param key="trust-store-path" value="${jboss.server.data.dir}/hornetq/hornetq.test.truststore"/>
    <param key="trust-store-password" value="test1234"/>
  </acceptor>
...
</acceptors>

Finally, I deployed a MDB on JBoss that listened for the messages send from an application running on Weblogic:

@MessageDriven(name = "TestMDB", activationConfig = {
  @ActivationConfigProperty(propertyName = "acknowledgeMode",
                            propertyValue = "Auto-acknowledge"),
  @ActivationConfigProperty(propertyName = "destinationType",
                            propertyValue = "javax.jms.Queue"),
  @ActivationConfigProperty(propertyName = "destination",
                            propertyValue = "jms/TestQueue")
})
public class TestMDB implements MessageListener {
  static final Logger logger = Logger.getLogger("TestMDB");

  public void onMessage(Message message) {
    TextMessage msg = null;

    try {
      if (message instanceof TextMessage) {
        msg = (TextMessage) message;
        logger.info("MESSAGE BEAN: Message received: " + msg.getText());
      } else {
        logger.warning("Message of wrong type: " + 
                               message.getClass().getName());
      }
    } catch (JMSException e) {
      logger.severe("TestMDB.onMessage: JMSException: " + e.toString());
      e.printStackTrace();
    } catch (Throwable te) {
      logger.severe("TestMDB.onMessage: Exception: " + te.toString());
      te.printStackTrace();
    }
  }
}

But, how to access to a secured queue? The answer was to configure the following piece with the user and password into the jboss.xml file:

<enterprise-beans>
  <message-driven>
  <ejb-name>TestMDB</ejb-name>
  <mdb-user>testUser</mdb-user>
  <mdb-passwd>test1234</mdb-passwd>
  </message-driven>
</enterprise-beans>

References


Advertisements

One Comment on “Securing a JMS bridge between Weblogic and HornetQ”


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s