Click here to Skip to main content
15,880,725 members
Articles / Programming Languages / C#
Tip/Trick

Connecting to IBM MQ (with SSL)

Rate me:
Please Sign up or sign in to vote.
5.00/5 (6 votes)
17 Jan 2023CPOL7 min read 38.8K   12   12
All items needed to successfully connect to IBM MQ
Connecting to IBM MQ is really an annoying task, whether for the configuration side or programming side. In this post, I will go through all the items needed to successfully connect to IBM MQ.

Introduction

Supporting IBM MQ in your code is not an easy task. I can say the main reason for that is the lack of samples, very complicated configurations, lack of proper and easy documentation and last but not the least, a very bad user experience by IBM itself.

Background

To be able to understand this tip, you need the following:

  • Basic programming knowledge
  • IBM MQ installed (information in this post has been tested on versions 7.5, 8.0 and 9.0).
  • This code was tested using .NET Framework 4.7.2, but I am sure the code will work fine with 4.5 and 3.5.
  • This code was tested using IBM MQ DLL's version 8.0.0.5 amqmdnet.dll, amqmdxcs.dll.

Using the Code

Configuration - Normal Mode

Before we start our code, we need to start the proper configuration of our IBM MQ, the best and easiest way is through command. There are many ways to configure it, so if you prefer another way, that's Ok, as long as you know it’s working fine. Also, many of the below commands might not seem necessary.

*** Please note that the below configurations are not suitable for production servers. ***

Before We Start With Ibm Mq Configuration, Let's Create a New Windows User and Call It Mquser. This User Must Be a Member of the Group "Mqm". This Group Will Be Available After Installing Ibm Mq.

Create a New Queue Manager with name QM:

crtmqm QM

Start Queue Manager:

strmqm QM

Start MQSC to execute commands for our Queue Manager:

runmqsc QM

// Expected Output: 
// 5724-H72 (C) Copyright IBM Corp. 1994, 2011.  ALL RIGHTS RESERVED.
// Starting MQSC for queue manager QM.

Create a new Local Queue with name (Queue1):

DEFINE QLOCAL (QUEUE1)

// Expected Output:      
// 1 : DEFINE QLOCAL (QUEUE1)
// AMQ8006: WebSphere MQ queue created.

Disable CHLAUTH rules:

ALTER QMGR CHLAUTH (DISABLED)

// Expected Output: 
// 2 : ALTER QMGR CHLAUTH (DISABLED)
// AMQ8005: WebSphere MQ queue manager changed.

Create a new Channel with name CHANNEL1 and set the value of MCAUSER to our user MQUser:

DEFINE CHANNEL (CHANNEL1) CHLTYPE (SVRCONN) TRPTYPE (TCP) MCAUSER('MQUser')

// Expected Output: 
// 3 : DEFINE CHANNEL (CHANNEL1) CHLTYPE (SVRCONN) TRPTYPE (TCP)
// AMQ8014: WebSphere MQ channel created.

Create a listener:

DEFINE LISTENER (LISTENER1) TRPTYPE (TCP) CONTROL (QMGR) PORT (1414)

// Expected Output: 
// 4 : DEFINE LISTENER (LISTENER1) TRPTYPE (TCP) CONTROL (QMGR) PORT (1414)
// AMQ8626: WebSphere MQ listener created.

Start our listener:

START LISTENER (LISTENER1)

// Expected Output: 
// 5 : START LISTENER (LISTENER1)
// AMQ8021: Request to start WebSphere MQ listener accepted.

Last command, close command:

end

// Expected Output: 
// 6 : end
// 6 MQSC commands read.
// No commands have a syntax error.
// All valid MQSC commands were processed.

Quick Connect Test

Using the below, you can easily connect to IBM MQ, noting the following:

  • UTF-8 is not a must, you can use UTF-16.
  • Many optional params not mentioned (below sample) are properties of object queueMessage if needed:
    • CorrelationId
    • MessageId
    • ReplyToQueueName
  • The code will type IBM MQ error code. A full list of the error codes can be found on the IBM website.
  • Username and Password in our configuration is not needed, uncomment the username / password assignment if needed.
C#
using IBM.WMQ;
using System;
using System.Collections;
using System.Text;

namespace MQTest
{
    class Program
    {
        static void Main(string[] args)
        {
            string strQueueManagerName = "QM";
            string strChannelName = "CHANNEL1";
            string strQueueName = "QUEUE1";
            string strServerName = "127.0.0.1";
            int intPort = 1414;
            string strMsg = "Hello IBM, this is a message";

            Hashtable queueProperties = new Hashtable
            {
                { MQC.HOST_NAME_PROPERTY, strServerName },
                { MQC.CHANNEL_PROPERTY, strChannelName },
                { MQC.PORT_PROPERTY, intPort },
                { MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED }
            };

            //Set Username
            //MQEnvironment.UserId = "User";

            //Set Passowrd
            //MQEnvironment.Password = "123";

            //Define a Queue Manager
            try
            {
                MQQueueManager myQM = new MQQueueManager
                                      (strQueueManagerName, queueProperties);

                //Define a Message
                MQMessage queueMessage = new MQMessage();
                queueMessage.Format = MQC.MQFMT_STRING;
                queueMessage.CharacterSet = Encoding.UTF8.CodePage;
                queueMessage.Write(Encoding.UTF8.GetBytes(strMsg));

                //Define a Queue
                var queue = myQM.AccessQueue
                    (strQueueName, MQC.MQOO_OUTPUT + MQC.MQOO_FAIL_IF_QUIESCING);
                MQPutMessageOptions queuePutMessageOptions = new MQPutMessageOptions();
                queue.Put(queueMessage, queuePutMessageOptions);
                queue.Close();
                Console.WriteLine("Success");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            Console.ReadLine();
        }
    }
}

Configuration - SSL

Now let’s start the complicated part - configuring a secure connection between IBM MQ and your client code. Before we start, there are many important notes that you need to know:

  • There are two ways to connect to IBM MQ with SSL, the first one which the client shares is its certificate. And the other way is without client sharing the certificate.
  • This code connects to IBM MQ over SSL using what is called "anonymous IBM MQ connection". More details can be found here. In this mode, the client doesn’t send its certificate.
  • During my work with IBM, I found that many of the parameters defined inside IBM MQ assemblies are not used and even useless. I might be mistaken but all evidences show otherwise. Through this post, I will add the word (useless) next to each of these parameters, maybe someone will explain this to me and to everyone else in the comments of this article.

To start SSL configuration with SSL, let's go back to the command prompt:

  1. Navigate to SSL folder under your Queue Manager folder, this can be found under your installation location which by default is: "C:\Program Files (x86)\IBM\WebSphere MQ\Qmgrs\QM\ssl":
    pushd "C:\Program Files (x86)\IBM\WebSphere MQ\Qmgrs\QM\ssl"
  2. Execute command to create the ssl repository with a name matching your Queue manager name and password of 12345.
    runmqckm -keydb -create -db QM.kdb -pw 12345 -type cms -stash 
  3. Let's create a self signed certificate so we can use it for our testing:
    C#
    runmqckm -cert -create -db QM.kdb -dn "CN=QM,OU=QM,O=SunJ,L=Amman,S=Amman,C=JO" 
    -pw 12345 -label ibmwebspheremqqm -size 2048 -expire 365 -sig_alg SHA256_WITH_RSA 
    It's very important to notice the following:
    1. QM.kdb is the repository that we created in Step 2 which matches the Queue Manager name.
    2. -label in the command must be ibmwebspheremq followed by QM our Queue Manager name in lower case.
    3. All certificate params like 'L=, S=, C=' can be changed as you wish.
    4. The remaining param must be left as it is, unless you know what exactly you are doing.
  4. Extract the certificate?

    We are not going to extract the certificate here as we mentioned above, we will be connecting without sending a certificate from the client side. A very important note in case you want to use the other way for connecting is:

    1. IBM MQ client assemblies go to the trusted store and only loads a certificate with the name ibmwebspheremq followed by your local machine user that is running the code in lower case. This takes me to the first (useless) parameter in IBM MQ assemblies which is MQEnvironment.CertificateLabel or MQC.label.

      This was very strange to me... I even decompiled IBM assembly to see if it’s actually used or not and below is the only code that is used to load the certificate. It might be there for future use, but for sure, it’s very confusing and misleading.

      C#
      RemoteCertificateValidationCallback(true),
      new LocalCertificateSelectionCallback(this.FixClientCertificate));
      var storeLocation = StoreLocation.LocalMachine;
      X509Store x509Store = new X509Store(StoreName.My, storeLocation);
      x509Store.Open(OpenFlags.OpenExistingOnly);
      X509Certificate2Collection x509Certificate2Collection =
                                      new X509Certificate2Collection();
      X509Certificate2Enumerator enumerator =
                                 x509Store.Certificates.GetEnumerator();
      var clientCertName =
          string.Concat("ibmwebspheremq", Environment.UserName.ToLower());
      while (enumerator.MoveNext())
      {
          X509Certificate2 current = enumerator.Current;
          if (current.FriendlyName.ToLower() != clientCertName)
          {
               continue;
          }
          x509Certificate2Collection.Add(current);
      }
      

      More details about this from IBM website under IBM WebSphere MQ client.

    2. As you can see in IBM code, it’s looking for the Friendly name to find the certificate, which will be empty if you use the runmqckm -cert -extract command. My recommendation is to use PowerShell to verify your license friendly name and change it. Otherwise, your code won’t pick it up.
  5. Configure your Queue Manager to use SSL:
    1. Right click your queue manager and choose Properties.
    2. From the left menu, choose SSL.
    3. In the SSL repository, set the location and the name of the repository that we created in the first step "QM.kdb" but do not add the extension with it. The final path will be C:\Program Files (x86)\IBM\WebSphere MQ\qmgrs\QM\ssl\QM. A very common mistake is either to add the extension or forget the name of repository, unfortunately IBM WebSphere will not notify that you have put invalid key at all.

      Image 1

    4. Now click OK, then Yes to the confirmation dialog.
  6. The final step is configuring your Channel:
    1. Right click your channel and click Properties.
    2. Again, from the right menu, choose SSL.
      • We need to set the SSL Cipher Specs value to "TLS_RSA_WITH_AES_128_CBC_SHA256", but before we do this brings our 2nd (useless) parameter "MQEnvironment.SSLCipherSpec" or "MQC.SSL_CIPHER_SPEC_PROPERTY".

        You can set this parameter in your code to whatever you want, it won't make any difference. In fact, the client will use windows default cipher specs which is set in your group policy which usually defaults to TLS_RSA_WITH_AES_128_CBC_SHA256. If this was not the case, you can configure it with the following steps:

      • From the Group Policy Management Console, go to Computer Configuration > Administrative Templates > Network > SSL Configuration Settings.

      • Double-click SSL Cipher Suite Order, and then click the Enabled option.

      • Right-click SSL Cipher Suites box and select Select all from the pop-up menu.

        Image 2

      • Replace the list in the SSL Cipher Suites with TLS_RSA_WITH_AES_128_CBC_SHA256 .

      • Click OK or Apply.

This is even more strange than the certificate label - you can see many of the samples on IBM Website show that you need to set the value in your code as you configured it inside your channel. But what it actually does is it just tells the client to use SSL code. So imagine this is a flag that is called "Use SSL" or not.

You can try to change it to TLS_RSA_WITH_AES_256_CBC_SHA256 in both your code and Channel SSL configuration and you will get the below error inside the event viewer.

Image 3

  1. Final step and as we mentioned before, our client code will not send a certificate from its side, so we need to set SSL Authentication value to Optional.

    Image 4

  2. Click Ok.

Modify Code to Support SSL

Our code won't work anymore, so let's add few more lines to modify our code with the SSL, all that we need to add is:

C#
MQEnvironment.SSLCipherSpec = "TLS_RSA_WITH_AES_256_CBC_SHA256";

As I mentioned before, although the SSLCipherSpec is useless to set Cipher Specs, it works as a flag to switch on SSL mode.

Full Final Code

C#
using IBM.WMQ;
using System;
using System.Collections;
using System.Text;

namespace MQTest
{
    class Program
    {
        static void Main(string[] args)
        {
            string strQueueManagerName = "QM";
            string strChannelName = "CHANNEL1";
            string strQueueName = "QUEUE1";
            string strServerName = "127.0.0.1";
            int intPort = 1414;
            string strMsg = "Hello IBM, this is a message";

            //Enable SSL
            MQEnvironment.SSLCipherSpec = "TLS_RSA_WITH_AES_256_CBC_SHA256";

            Hashtable queueProperties = new Hashtable
            {
                { MQC.HOST_NAME_PROPERTY, strServerName },
                { MQC.CHANNEL_PROPERTY, strChannelName },
                { MQC.PORT_PROPERTY, intPort },
                { MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED }
            };

            //Set Username
            //MQEnvironment.UserId = "User";

            //Set Passowrd
            //MQEnvironment.Password = "123";

            //Define a Queue Manager
            try
            {
                MQQueueManager myQM = 
                       new MQQueueManager(strQueueManagerName, queueProperties);

                //Define a Message
                MQMessage queueMessage = new MQMessage();
                queueMessage.Format = MQC.MQFMT_STRING;
                queueMessage.CharacterSet = Encoding.UTF8.CodePage;
                queueMessage.Write(Encoding.UTF8.GetBytes(strMsg));

                //Define a Queue
                var queue = myQM.AccessQueue
                (strQueueName, MQC.MQOO_OUTPUT + MQC.MQOO_FAIL_IF_QUIESCING);
                MQPutMessageOptions queuePutMessageOptions = new MQPutMessageOptions();
                queue.Put(queueMessage, queuePutMessageOptions);
                queue.Close();
                Console.WriteLine("Success");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            Console.ReadLine();
        }
    }
}

Points of Interest

IBM MQ is one of the leading queuing systems that is created and maybe the most commonly used. However, IBM fails badly by making what's supposed to be a very easy job a really long and hard process of trial and error.

Between the lack of proper validation on IBM MQ WebSphere, hidden properties and rules that can be seen by special command lines "Such as main block rule" to the unused misleading variables and configurations inside the published assemblies.

Based on my findings while working with IBM, I am sure there are many other params that can be considered as unused as well. Although on the other hand, all of these might be a mistake on my side.

History

  • 19th May, 2020: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead
United Arab Emirates United Arab Emirates
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionMQRC_HOST_NOT_AVAILABLE with version 7 and MQRC_KEY_REPOSITORY_ERROR for version 9 Pin
Sudhakaran Nair6-Feb-24 2:02
Sudhakaran Nair6-Feb-24 2:02 
QuestionCool article, unfortunatelly it is not working more Pin
Yevhen Cherkes2-Aug-23 2:01
Yevhen Cherkes2-Aug-23 2:01 
AnswerRe: Cool article, unfortunatelly it is not working more Pin
phil-newman 20231-Dec-23 4:46
phil-newman 20231-Dec-23 4:46 
QuestionGood article Pin
rjmoses16-Jan-23 23:33
professionalrjmoses16-Jan-23 23:33 
QuestionCertificate Label Pin
Member 782859727-Jun-22 2:06
Member 782859727-Jun-22 2:06 
QuestionHOST NOT AVAILABLE ERROR WITH SSL Pin
howardz17-Jun-22 5:24
howardz17-Jun-22 5:24 
QuestionWell Said Pin
Member 1558192128-Mar-22 8:15
Member 1558192128-Mar-22 8:15 
GeneralMy vote of 5 Pin
mohammed barqawi24-May-20 9:26
mohammed barqawi24-May-20 9:26 
QuestionBetter do an article about IBM MQ on Cloud Pin
Издислав Издиславов20-May-20 20:15
Издислав Издиславов20-May-20 20:15 
SuggestionA few extra hints Pin
Morag Hughson18-May-20 23:39
Morag Hughson18-May-20 23:39 
AnswerRe: A few extra hints Pin
Sufyan S Jabr19-May-20 9:09
Sufyan S Jabr19-May-20 9:09 
AnswerRe: A few extra hints Pin
Morag Hughson19-May-20 23:37
Morag Hughson19-May-20 23:37 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.