0
votes

I have enabled SSL on JBoss EAP 7.2 by creating a security realm & mapped that to management interface. that works fine. Now I try to secure the JMS queues (ActiveMQ) on JBoss EAP. First I specifies a queue on standalone-full.xml and mentioned a remote connection factory by pointing to a https-connector & acceptor.

<subsystem xmlns="urn:jboss:domain:messaging-activemq:4.0">
    <server name="default">
        <journal pool-files="10"/>
        <security-setting name="#">
            <role name="guest" send="true" consume="true" create-non-durable-queue="true" delete-non-durable-queue="true"/>
        </security-setting>
        <address-setting name="#" dead-letter-address="jms.queue.DLQ" expiry-address="jms.queue.ExpiryQueue" max-size-bytes="10485760" page-size-bytes="2097152" message-counter-history-day-limit="10"/>
        <http-connector name="http-connector" socket-binding="http" endpoint="http-acceptor"/>
        <http-connector name="http-connector-throughput" socket-binding="http" endpoint="http-acceptor-throughput">
            <param name="batch-delay" value="50"/>
        </http-connector>
        <http-connector name="https-connector" socket-binding="https" endpoint="https-acceptor"/>
        <http-connector name="https-connector-throughput" socket-binding="https" endpoint="https-acceptor-throughput">
            <param name="batch-delay" value="50"/>
        </http-connector>
        <in-vm-connector name="in-vm" server-id="0">
            <param name="buffer-pooling" value="false"/>
        </in-vm-connector>
        <http-acceptor name="http-acceptor" http-listener="default"/>
        <http-acceptor name="http-acceptor-throughput" http-listener="default">
            <param name="batch-delay" value="50"/>
            <param name="direct-deliver" value="false"/>
        </http-acceptor>
        <http-acceptor name="https-acceptor" http-listener="https"/>
        <http-acceptor name="https-acceptor-throughput" http-listener="https">
            <param name="batch-delay" value="50"/>
            <param name="direct-deliver" value="false"/>
        </http-acceptor>
        <in-vm-acceptor name="in-vm" server-id="0">
            <param name="buffer-pooling" value="false"/>
        </in-vm-acceptor>
        <jms-queue name="ExpiryQueue" entries="java:/jms/queue/ExpiryQueue"/>
        <jms-queue name="DLQ" entries="java:/jms/queue/DLQ"/>
        <jms-queue name="testQueue" entries="java:jboss/exported/wmasTestQueue java:/jms/queue/wmasTestQueue" durable="true"/>
        <connection-factory name="InVmConnectionFactory" entries="java:/ConnectionFactory" connectors="in-vm"/>
        <connection-factory name="RemoteConnectionFactory" entries="java:jboss/exported/jms/RemoteConnectionFactory" connectors="http-connector"/>
        <connection-factory name="RemoteConnectionFactoryHttps" entries="java:jboss/exported/jms/RemoteConnectionFactoryHTTPS" connectors="https-connector"/>
        <pooled-connection-factory name="activemq-ra" entries="java:/JmsXA java:jboss/DefaultJMSConnectionFactory" connectors="in-vm" transaction="xa"/>
    </server>
</subsystem>

And I have updated the remoting subsytem to use connector-ref as https from default

<subsystem xmlns="urn:jboss:domain:remoting:4.0">
    <http-connector name="http-remoting-connector" connector-ref="https" security-realm="ApplicationRealm"/>
</subsystem>

When I try to access the http-remoting://127.0.0.1:8443 from a standalone Java class, I get below error while acquiring connection factory

WFNAM00018: Failed to connect to remote host [Root exception is java.io.IOException: Invalid response]
    at org.wildfly.naming.client.remote.RemoteNamingProvider.getPeerIdentityForNaming(RemoteNamingProvider.java:110)
    at org.wildfly.naming.client.remote.RemoteNamingProvider.getPeerIdentityForNaming(RemoteNamingProvider.java:53)
    at org.wildfly.naming.client.NamingProvider.getPeerIdentityForNamingUsingRetry(NamingProvider.java:105)
    at org.wildfly.naming.client.remote.RemoteNamingProvider.getPeerIdentityForNamingUsingRetry(RemoteNamingProvider.java:91)
    at org.wildfly.naming.client.remote.RemoteContext.lambda$lookupNative$0(RemoteContext.java:189)
    at org.wildfly.naming.client.NamingProvider.performExceptionAction(NamingProvider.java:222)
    at org.wildfly.naming.client.remote.RemoteContext.performWithRetry(RemoteContext.java:100)
    at org.wildfly.naming.client.remote.RemoteContext.lookupNative(RemoteContext.java:188)
    at org.wildfly.naming.client.AbstractFederatingContext.lookup(AbstractFederatingContext.java:74)
    at org.wildfly.naming.client.AbstractFederatingContext.lookup(AbstractFederatingContext.java:60)
    at org.wildfly.naming.client.WildFlyRootContext.lookup(WildFlyRootContext.java:144)
    at javax.naming.InitialContext.lookup(InitialContext.java:417)
    at com.cibc.jboss.queue.PostMessage.main(PostMessage.java:43)
Caused by: java.io.IOException: Invalid response

Please help to resolve. Am I missing any config.

1

1 Answers

0
votes

The best way to secure JMS on EAP 7.2 is using Elytron. Secure the server with Elytron using --interactive mode. this will sets you up keystore & truststore with sslConext created on Elyton subsystem.

Your server standalone will look like this;

-<tls>
-<key-stores>
-<key-store name="key-store-8ce838a4-6109-46e4-b243-a71489bb842f">
<credential-reference clear-text="password"/>
<implementation type="JKS"/>
<file relative-to="jboss.server.config.dir" path="jks-source.jks" required="false"/>
</key-store>
</key-stores>
-<key-managers>
-<key-manager name="key-manager-8ce838a4-6109-46e4-b243-a71489bb842f" key-store="key-store-8ce838a4-6109-46e4-b243-a71489bb842f">
<credential-reference clear-text="password"/>
</key-manager>
</key-managers>
-<server-ssl-contexts>
<server-ssl-context name="ssl-context-8ce838a4-6109-46e4-b243-a71489bb842f" key-manager="key-manager-8ce838a4-6109-46e4-b243-a71489bb842f" use-cipher-suites-order="false" authentication-optional="false" need-client-auth="false" want-client-auth="false" protocols="TLSv1.2" cipher-suite-filter="DEFAULT"/>
</server-ssl-contexts>
</tls>

Enable ssl on httpconnector in the activemq subsystem

-<http-connector name="http-connector2" socket-binding="https" endpoint="http-acceptor2">

<param name="ssl-enabled" value="true"/>

</http-connector>

If the client is having its own trustore, be sure to add the server's public certificate to its truststore. to test the above, we can use standalone JMS client posting request to https-remoting://localhost:8443. Its a bad idea to add the self signed certificate from server to include in JDK's truststore (cacerts) - but thats a quick option to test out the secured JMS on Jboss EAP.

public class PostMessage {

    // Set up all the default values
    private static final String DEFAULT_MESSAGE = "Hello, World! successfull";
    private static final String DEFAULT_CONNECTION_FACTORY = "jms/RemoteConnectionFactory";
    private static final String DEFAULT_DESTINATION = "TestQueue";
    private static final String DEFAULT_MESSAGE_COUNT = "1";
    private static final String DEFAULT_USERNAME = "jmsuser";
    private static final String DEFAULT_PASSWORD = "jmsuser123";
    private static final String INITIAL_CONTEXT_FACTORY = "org.wildfly.naming.client.WildFlyInitialContextFactory";
    private static final String PROVIDER_URL = "https-remoting://127.0.0.1:8443";


    public static void main(String[] args) throws JMSException {

        Context namingContext = null;

       // System.setProperty("javax.net.debug","all");

        try {
             String userName = System.getProperty("username", DEFAULT_USERNAME);
             String password = System.getProperty("password", DEFAULT_PASSWORD);

            // Set up the namingContext for the JNDI lookup
            final Properties env = new Properties();
            env.put(Context.INITIAL_CONTEXT_FACTORY, INITIAL_CONTEXT_FACTORY);
            env.put(Context.PROVIDER_URL, System.getProperty(Context.PROVIDER_URL, PROVIDER_URL));
            namingContext = new InitialContext(env);

            // Perform the JNDI lookups
            String connectionFactoryString = System.getProperty("connection.factory", DEFAULT_CONNECTION_FACTORY);
            ConnectionFactory connectionFactory = (ConnectionFactory) namingContext.lookup(connectionFactoryString);
            System.out.println("Able to look up connection factory with the naming context "  );
            Queue destination = (Queue) namingContext.lookup(DEFAULT_DESTINATION);
            System.out.println("Able to look up Queue with the naming context" );
                JMSContext jmsContext = connectionFactory.createContext(DEFAULT_USERNAME, DEFAULT_PASSWORD);
            jmsContext.createProducer().send(destination, DEFAULT_MESSAGE);
            System.out.println("><><><><><><>< MESSAGE POSTED <><><><><><><>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" );

        } catch (NamingException e) {
            e.printStackTrace();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            if (namingContext != null) {
                try {
                    namingContext.close();
                } catch (NamingException e) {
                }
            }
        }
    }
}