Securing application connections in C MQI & JMS programs
This document covers connecting securely to an MQ SaaS queue manager using "C MQI" and "JMS" applications. You will need the application user name and password which you downloaded in the prerequisite steps. You will also need the MQ client for your operating system, which may be part of a full MQ installation, or may be downloaded separately from here.
Prerequisites
- For establishing a secured connection to MQ SaaS queue manager, you must first set up TLS encryption on the MQ channel. Refer Enabling TLS security for MQ channels in MQ SaaS
- If you are not familiar with how to connect an application to an MQ SaaS queue manager, there is documentation here: Connecting a sample application to a queue manager
- To use the JSON CCDT definition for your application, you must have a 9.1.2 (or above) installation of the client.
Tasks specific to the C MQI Program
Alter the client channel definition table (CCDT)
As part of the prerequisites, you downloaded the JSON CCDT queue manager description earlier. By default, it does not contain the cipher specifications that you associated with the channels, so you have to add that now, adding a transmissionSecurity definition for each channel.
For example:
"channel": [
{
"name": "CLOUD.ADMIN.SVRCONN",
"clientConnection": {
"connection": [
{
"host": "myqueuemanager.qm2.us-south.mq.appdomain.cloud",
"port": 31500
}
],
"queueManager": "MQ_TEST_ONE"
},
"transmissionSecurity": {
"cipherSpecification": "SSL_RSA_WITH_AES_128_CBC_SHA256",
},
"type": "clientConnection"
},
The cipher specification at the client end has been specified as SSL_RSA_WITH_AES_128_CBC_SHA256. It could be any TLS 1.2 cipher specification, as the server end was set to accept ANY_TLS12_OR_HIGHER.
Export the necessary environment variables
- Open command line interface and navigate to MQ C Samples directory.
- The location of this will depend on your operating system - it would be
/var/mqm/Tools/Samples/C
(Linux),C:\Program Files\IBM\MQ\Tools\c\Samples
(Windows), or on Mac, where you have installed the toolkit, for example~/mytoolkit/IBM-MQ-Toolkit-Mac-x64-9.1.2.0/samp/bin
.
- The location of this will depend on your operating system - it would be
- Set the
MQSSLKEYR
environment variable, this is the full path from the system root to the key store file. Note that the filename requires no suffix - so for a key store named key.kdb, specify just "key".- For Windows, run
set MQSSLKEYR=c:\mystore\key
- For Mac or Linux,
export MQSSLKEYR=/Users/you/store/key
- For Windows, run
- The path to the CCDT file can be set in one of two ways:
- Set the environment variable
MQCCDTURL
, this is file path from the system root to the ccdt file to which you added the cipherSpecification earlier.- For Windows, run
set MQCCDTURL=c:\mydefinitions\connection_info_ccdt.json
- For Mac or Linux, run
export MQCCDTURL=file:///Users/you/definitions/connection_info_ccdt.json
- For Windows, run
- Set the environment variables
MQCHLLIB
andMQCHLTAB
.MQCHLLIB
is the full path to the directory of your ccdt file andMQCHLTAB
is the filename of the ccdt file to which you added the cipherSpecification earlier.- For Windows, run
set MQCHLLIB=c:\mydefinitions
andset MQCHLTAB=connection_info_ccdt.json
- For Mac or Linux, run
export MQCHLLIB=/Users/you/definitions
andexport MQCHLTAB=connection_info_ccdt.json
- For Windows, run
- Set the environment variable
- Set the
MQSAMP_USER_ID
environment variable, this is the user id you would like to connect as. For applications this is the application credential name which you downloaded earlier- For Windows, run
set MQSAMP_USER_ID=<yourusername>
- For Mac or Linux,
export MQSAMP_USER_ID=<yourusername>
- For Windows, run
- Ensure the
MQSERVER
environment variable is not set by runningunset MQSERVER
- Run the sample
amqsputc
, specifying queue name and queue manager name, for example:amqsputc DEV.QUEUE.1 QM1
- Enter the password for the application credential being used
- Once the message 'target queue is DEV.QUEUE.1' appears on command line, it is ready to send messages:
- Type the message data/string and when ready press “ENTER” to send the message.
- An empty string “ENTER” will end the sample.
- You can use
amqsgetc
to receive the messages sent.amqsgetc DEV.QUEUE.1 <YOURQMGRNAME>
The C MQI sample program is using a secured connection to send/receive messages.
Tasks specific to the JMS Program
If you are not familiar with the JMS sample program, there is a full tutorial on how to install and run the sample without TLS here: https://developer.ibm.com/learningpaths/ibm-mq-badge/write-run-first-mq-app/
The sample above runs on the IBM Java 1.8 SDK on Windows and Linux. At the time of writing, we also tried this using the Oracle 1.8 SDK, but were unable to get the connection working - there was a cipher suite mismatch.
When you can run the JMS sample, you now need to alter it to accept the cipher specification:
- Update the MQ JMS sample for making a secured connection:
- Navigate to MQ JMS Samples directory. The location will vary depending on your operating system. By default, these will be $MQ_INSTALLATION_PATH/samp/jms/samples on Linux and %MQ_INSTALLATION_PATH%\tools\jms\samples on Windows
- Use any editor to open the simple/JmsPut.java program.
- Add following new properties to the jms program, just after creating JMS ConnectionFactory instance.
System.setProperty("javax.net.ssl.keyStore", "/Users/you/store/key.kdb"); System.setProperty("javax.net.ssl.keyStorePassword", "my_store_password"); cf.setStringProperty(WMQConstants.USERID, "Your app user ID"); cf.setStringProperty(WMQConstants.PASSWORD, "Your APIKEY"); cf.setStringProperty(WMQConstants.WMQ_SSL_CIPHER_SPEC, "ANY_TLS12_OR_HIGHER"); cf.setStringProperty(WMQConstants.WMQ_CHANNEL, "CLOUD.APP.SVRCONN"); cf.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_CLIENT);
- The property keyStore should be the full path to the keystore which you created in Enabling TLS security for MQ channels in MQ SaaS
- The cipher specification at the client end could be any TLS 1.2 specification, but it is recommended that you set this to ANY_TLS12_OR_HIGHER.
- Find the values for hostname, port, and queue manager properties gathered from MQ SaaS queue manager details and set them in the JMS program as shown below:
cf.setStringProperty(WMQConstants.WMQ_HOST_NAME, "Your_Queue_Manager_Host_Name_From_CCDT"); cf.setIntProperty(WMQConstants.WMQ_PORT, "10305"); cf.setStringProperty(WMQConstants.WMQ_QUEUE_MANAGER, "Your_Queue_Manager_Name_From_CCDT");
- Save and Close the editor.
- Compile and Run the JMS Sample:
- Open a command line interface to use in the steps.
- If you have not already done this - update System class path to include MQ JMS jars and JMS samples class folder.
On Linux: export CLASSPATH=$MQ_INSTALLATION_PATH/java/lib/com.ibm.mqjms.jar:$MQ_INSTALLATION_PATH/samp/jms/samples: On Windows: Set CLASSPATH=%MQ_INSTALLATION_PATH%\java\lib\com.ibm.mqjms.jar;%MQ_INSTALLATION_PATH%\tools\jms\samples;
- Navigate to $MQ_INSTALLATION_PATH/samp/jms/samples and run
javac simple/JmsPut.java
- Run the JMS Program
java simple/JmsPut
This JMS Program sends and receives a message using a secured connection. The output should look like this:
root@d93d60e4f179:/# java -cp ./com.ibm.mq.allclient-9.0.4.0.jar:./javax.jms-api-2.0.1.jar:. com.ibm.mq.samples.jms.JmsPutGet
Sent message:
JMSMessage class: jms_text
JMSType: null
JMSDeliveryMode: 2
JMSDeliveryDelay: 0
JMSDeliveryTime: 1563884375664
JMSExpiration: 0
JMSPriority: 4
JMSMessageID: ID:414d51204d515f65735f663920202020806f355d04ff4924
JMSTimestamp: 1563884375664
JMSCorrelationID: null
JMSDestination: queue:///DEV.QUEUE.1
JMSReplyTo: null
JMSRedelivered: false
JMSXAppID: JmsPutGet (JMS)
JMSXDeliveryCount: 0
JMSXUserID: app1
JMS_IBM_PutApplType: 28
JMS_IBM_PutDate: 20190723
JMS_IBM_PutTime: 12193624
Your lucky number today is 633
Received message:
Your lucky number today is 633
SUCCESS