ActiveMQ support for TLSv1.2 - jms

I'm trying to get ActiveMQ to support a TLSv1.2. I'm using activemq v5.14.5. The fix talked about in Create ActiveMQ Connection on TLS1.2 did not work. When I stepped through the code I see that the
context.setSSLContext(sslContext);
SslContext.setCurrentSslContext(context);
Connection connection = factory.createConnection(loginName, pwd);
call to factory.createConnection() actually doesn't use the value that was just set, but instead creates a new SSL context using the hard coded default of "TLS". I observed this in the debugger.
Any other suggestions are welcome. I think the topic "configuring transports" at http://activemq.apache.org/configuring-transports.html may hold the solution but I haven't tried it yet.

The default embedded ActiveMQ broker configuration does not create an SSL transport connector. If you manually added an SSL transport connector, then you may have restricted the SSL protocols supported by the broker using the option transport.enabledProtocols:
<transportConnector name="ssl" uri="ssl://localhost:61617?transport.enabledProtocols=TLSv1.2"></transportConnector>
This configuration restricts the SSL connector of ActiveMQ to only support TLSv1.2. Other TLSv1, TLSv1.1, SSLv3 will not be supported.

Related

Is it possible to use OpenWire protocol with spring-boot-starter-artemis?

I set up ActiveMQ Artemis consumer using spring-boot-starter-artemis and JMS. I also launched broker locally and I aim to configure these to communicate over OpenWire protocol. To constrain communication to that protocol I modified acceptor in broker.xml (protocols=OPENWIRE). It looks like that:
<acceptor name="artemis">tcp://0.0.0.0:61616?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;amqpMinLargeMessageSize=102400;protocols=OPENWIRE;useEpoll=true;amqpCredits=1000;amqpLowCredits=300;amqpDuplicateDetection=true;supportAdvisory=false;suppressInternalManagementObjects=false</acceptor>
However, unfortunately I'm getting the following error:
org.springframework.jms.UncategorizedJmsException: Uncategorized exception occurred during JMS processing; nested exception is javax.jms.JMSException: Failed to create session factory; nested exception is ActiveMQConnectionTimedOutException[errorType=CONNECTION_TIMEDOUT message=AMQ219013: Timed out waiting to receive cluster topology. Group:null]
How can I configure the client to use OpenWire protocol?
What is the default protocol they communicate on? Before I constrained the communication, Artemis Console was presenting the connection has been established on CORE protocol, which as far as I understand collective protocol. Which one i target protocol they really communicate on and how can I check this out?
The reason you're receiving ActiveMQConnectionTimedOutException is because you trying to use spring-boot-starter-artemis to connect to an acceptor which is configured to only support the OpenWire protocol. This will never work because spring-boot-starter-artemis depends on artemis-jms-client which will only use the ActiveMQ Artemis "core" protocol, not OpenWire.
You should configure the acceptor in broker.xml to support core, e.g.:
protocols=CORE,OPENWIRE
If you want the client to use OpenWire then you need to use the OpenWire JMS client library from ActiveMQ "Classic."

Amazon MQ transforming AMQP message to JMS

I have a Python and Java Spring application communicating 2 ways. The stack is mostly built on Java/Spring so ActiveMQ and JMS were the logical choices. However, we added a Python application that needed to interact with the rest of the services so I used qpid proton (AMQP library) and added the following configuration inside the ActiveMQ configuration to get it working:
<transportConnectors>
<transportConnector name="openwire" uri="ssl://0.0.0.0:61617?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="amqps" uri="amqp+ssl://0.0.0.0:5671?maximumConnections=1000&wireFormat.maxFrameSize=104857600&transport.transformer=jms"/>
</transportConnectors>
which worked flawlessly on ActiveMQ and allowed to send/receive JMS TextMessage with an AMQP client.
Unfortunately, Amazon MQ refused this configuration and returned the following error:
The value 'amqp+ssl' of attribute 'name' on element 'transportConnector' is not valid with respect to its type, 'protocol'. and cvc-enumeration-valid: Value 'amqps' is not facet-valid with respect to enumeration '[openwire]'
AWS markets Amazon MQ as a managed ActiveMQ service but they seem to be lacking in functionalities since the mapping from AMQP to JMS has been available since version 5.8: https://activemq.apache.org/amqp and the Amazon MQ broker that I'm using is at version 5.15.12
I have tried adding the amp;transport.transformer=jms and transport.transformer=jms headers to the query string of the broker's URL, as well as using STOMP as the protocol (since it is a plain-text protocol) in the Python app instead of AMQP but none of these worked.
So, do you know any potential missing configurations or other ways I could send an AMQP message in my Python app and receive a JMS TextMessage in the Java app?
By default in the open source ActiveMQ 5.x code the AMQP transport already defaults to the JMS transformation so unless the Amazon version has altered that you shouldn't need to even set that explicitly if you want JMS transforms of the inbound AMQP messages. If they've altered that then you'd need to contact them to determine how to change that configuration.

How Amazon MQ service works without asking client to use TrustStore and KeyStore?

When we configure the SSL on standalone ActiveMQ, we may need to provide the TrustStore,TrustStore Password, KeyStore and KeyStore password in client code to connect to the Active MQ over SSL protocol but in case of AmazonMQ, though they have provided SSL endpoint, but we can connect to it simply without providing the trust and key related values.
Client code snippet for Simple ActiveMQ over SSL:
ActiveMQSslConnectionFactory connFactory = new ActiveMQSslConnectionFactory("ssl://<someHost>:61617");
String trustStore = "pathTo/client_new.ts";
String keyStore = "PathTo/client_new.ks";
try {
connFactory.setTrustStore(trustStore);
connFactory.setTrustStorePassword("password");
connFactory.setKeyStore(keyStore);
connFactory.setKeyStorePassword("password");
} catch (Exception e) {
e.printStackTrace();
}
Client code snippet for Amazon MQ over SSL:
ActiveMQConnectionFactory connFactory = new ActiveMQConnectionFactory("ssl://xyz.amazonaws.com:61617");
Basically, what make this difference?
Firstly AmazonMQ works on top of the ActiveMQ, amazon has written a wrapper layer over activeMQ so as functionality wise it works pretty much the same. AmazonMQ is managed Message Broker Service for ActiveMQ.
It manages everything related to space, configuring active/passive endpoints in different regions and some benefits mentioned in the below links.
https://docs.aws.amazon.com/amazon-mq/latest/developer-guide/welcome.html
Other benefits of amazonMQ is you can setup alerts and many more as part of using other services of amazon like upgrading activemq version to the latest.
Now coming to you application part, one good thing was the way you have configured activemq was via SSL connection, though activemq exposes tcp endpoint as well which can be connected by simply providing broker URL but in case of amazonMQ it does not exposes any TCP endpoint only way to connect is by providing SSL endpoint and related parameters.
Refer this link on how application is connected to amazonMQ:
https://docs.aws.amazon.com/amazon-mq/latest/developer-guide/amazon-mq-connecting-application.html

MQ SSL error, protocol is disabled or cipher suites are inappropriate

I have a MQ spring jms application that has been working fine using SSL channel. However after a recent java security patch that was applied the application stopped working with below error.
Caused by: com.ibm.mq.MQException: JMSCMQ0001: WebSphere MQ call failed with compcode '2' ('MQCC_FAILED') reason '2397' ('MQRC_JSSE_ERROR').
at com.ibm.msg.client.wmq.common.internal.Reason.createException(Reason.java:209) ~[com.ibm.mqjms-7.5.0.0.jar:7.5.0.0 - p000-L120604]
... 45 common frames omitted
Caused by: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
at sun.security.ssl.Handshaker.activate(Handshaker.java:438) ~[na:1.6.0_34]
at sun.security.ssl.SSLSocketImpl.kickstartHandshake(SSLSocketImpl.java:1414) ~[na:1.6.0_34]
I notice that the new java security file has this line added that is causing this failure in SSL connection to MQ.
jdk.tls.disabledAlgorithms=SSLv3
I can not get this line removed as this is shared environment, what are my options to make this work. I am using MQQueueConnectionFactory configured and injected into my spring JMS components.
Thank you
Can you not use this -
java.security.Security.setProperty("jdk.tls.disabledAlgorithms","")
This change was introduced in JDK8.
For reactive support purposes where you have to get this working (as soon as possible), comment/disable that policy in that security file. This will allow the Spring application to continue as it is before.
But you need to work towards a permanent fix either by using the TLS version of the same cipher or moving to a new TLS cipher.
You need to set matching SipherSpecs suited for TLS on both the server connection channel on the queue manager and your client.
This should help with the client side:
http://www-01.ibm.com/support/knowledgecenter/SSFKSJ_8.0.0/com.ibm.mq.dev.doc/q113220_.htm
While doing the QM side is easiest by using MQ Explorer, and just looking at the SSL properties of the server connection channel specified in the connection factory.

How does Spring mange websocket connections to RabbitMQ?

I have a game server that uses websocket for real time multiplayers. It is a Spring 4 application and I use RabbitMQ as my broker. This is my configuration:
<websocket:message-broker application-destination-prefix="/app">
<websocket:stomp-endpoint path="/portfolio">
<websocket:sockjs/>
</websocket:stomp-endpoint>
<websocket:simple-broker prefix="/queue, /topic"/>
</websocket:message-broker>
From a very small test with 4 clients I saw 4 connections open on Rabbit.
Does each client that connects to my server using websocket eventually open a new connection to the broker (RabbitMQ)? Can this be configured?
Yes, each websocket client gets its own TCP connection to the broker. The documentation has a section for connections to the broker (emphasis mine):
A STOMP broker relay maintains a single "system" TCP connection to the broker. This connection is used for messages originating from the server-side application only, not for receiving messages. [...]
The STOMP broker relay also creates a separate TCP connection for every connected WebSocket client. [ ... ]
If this can be configured or not I don't know, I'm not all that familiar with this part of Spring, but I assume it should be; Spring is open to extension. My suggestion is to post an issue on the spring-websocket-portfolio project and ask for specifics.
EDIT : OP opened the following issue on the spring-websocket-portfolio project.

Resources