Sunday, January 27, 2013

Spring & ActiveMQ SSL-enabled

In this blog I will show you how to configure ActiveMQ to use SSL as its transport.

Follow steps 1-4 on http://activemq.apache.org/how-do-i-use-ssl.html.

If running ActiveMQ as a server:
cd ~/activemq
vi conf/activemq.xml

Modify <transportConnector> to use SSL.
Before:
<transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireformat.maxFrameSize=104857600"/>
After:
<transportConnector name="openwire" uri="ssl://localhost:61616?maximumConnections=1000&amp;wireformat.maxFrameSize=104857600"/>

Add SSLContext to <broker>.
<sslContext>
    <sslContext 
      keyStore="/home/nbashir/broker.ks" keyStorePassword="your-password" 
      trustStore="/home/nbashir/client.ts" trustStorePassword="your-password" />
</sslContext>

If you are using spring, you need the following info in your application-context files for producer and consumer classes:

Producer  application-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:amq="http://activemq.apache.org/schema/core" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.noushin.spring.jms" />
    <context:annotation-config />

    <!-- ActiveMQ destinations to use -->
    <amq:queue id="destination" physicalName="TestQ" />
    
    <bean id="sslConnectionFactory" class="org.apache.activemq.ActiveMQSslConnectionFactory"
        p:brokerURL="ssl://localhost:61616"
        p:trustStore="client.ts"
        p:trustStorePassword="your-password" />
    
    <!-- Spring JMS Producer Configuration -->
    <bean id="jmsProducerTemplate" class="org.springframework.jms.core.JmsTemplate"
        p:connectionFactory-ref="sslConnectionFactory"
        p:defaultDestination-ref="destination"/>
        
</beans>

 Consumer applciation-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:amq="http://activemq.apache.org/schema/core" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jms="http://www.springframework.org/schema/jms" 
    xmlns:p="http://www.springframework.org/schema/p"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd
                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                        http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms.xsd">

    <context:component-scan base-package="com.noushin.spring.jms" />
    <context:annotation-config />
    
    <bean id="sslConnectionFactory" class="org.apache.activemq.ActiveMQSslConnectionFactory"
        p:brokerURL="ssl://localhost:61616"
        p:trustStore="client.ts"
        p:trustStorePassword="your-password" />
    
   <!-- JMS Consumer Configuration -->        
    <jms:listener-container container-type="default" 
                            connection-factory="sslConnectionFactory"
                            acknowledge="auto">
        <jms:listener destination="TestQ" ref="messageConsumer" />
    </jms:listener-container>
    
</beans>


Alternatively, you can configure ActiveMQ to run as a embedded JMS provider within your app. For that add the following lines to your application's application-context.xml
<!-- SSL Context --> 
<amq:broker useJmx="true" persistent="false">
    <amq:sslContext>
        <amq:sslContext 
            keyStore="/home/nbashir/broker.ks"
            keyStorePassword="your-password" 
            trustStore="/home/nbashir/client.ts"
            trustStorePassword="your-password" />
    </amq:sslContext>
    <amq:transportConnectors>
        <amq:transportConnector uri="ssl://localhost:61616" />
    </amq:transportConnectors>
</amq:broker>

2 comments:

  1. A usefull quick-setup. Good job!
    I also configured ActiveMQ over SSL for a geographically distribuited environment ( America-Europe). Pay attention to the client/server SSL handshake. For a huge amount of messages, the SSL layer could take a decent amount of CPU cycles to encrypt/decrypt the data. Could be much slower the use of SSL than the trasparent TCP. A possible solution could be to reuse the connection using the PooledConnectionFactory provided by ActiveMQ.

    ReplyDelete
  2. If using tomcat, don't forget the following:

    1. Edit ~tomcat/bin/setenv.sh
    2. Add:
    export CATALINA_OPTS="-Djavax.net.ssl.keyStore=/opt/zq/meter/conf/client.ks -Djavax.net.ssl.keyStorePassword=ur-passwd -Djavax.net.ssl.trustStore=/opt/zq/meter/conf/client.ts
    "

    ReplyDelete