Advanced Message Security with IBM WebSphere MQ

In these days I’m involving with some serious business with IBM WebSphere MQ …  🙂 . This is the last part of my IBM WebSphere MQ project. So I thought to share my experience with you.

IBM WebSphere MQ has a separate component called “Advanced Message Security aka AMS”, with this feature it enables you to encrypt message and puts it in your queue. Just don’t get me wrong , It doesn’t encrypt message when it leaves your application . Encryption happens when message reaches the IBM WebSphere MQ server. So you don’t need to break your existing code. Only thing you need to make sure , You have to install AMS component in your IBM MQ server.

Let’s say I’m in an intranet and my user name is “herath”(192.168.10.1) and I want to send a message to MQ server (192.168.10.2) . So in server there is an user “bobmquser” who has permission to read this message. So also my mq server in diffrent domain ( WMQSERVER\bobmqserver ) and I am in another domain (XXXX\herath). Therefore I’m going to connect as WMQSERVER\MUSR_MQADMIN. In this scenario I will set write permission to MUSR_MQADMIN and read permission to bobmquser.

Intranet

Intranet

First create an queue manager called QM_AMSTest , then local queue called XYZ and server-client channel called ABC and set it user as MUSR_MQADMIN

channel

channel

To test this message security create an “ALIAS” queue

Alias queue

Alias queue

Go to MQ server then select the queue manager (QM_AMSTest). First you need to set inquire and connect permissions to both users on queue manager.

Manager Authority

Manager Authority

Set Read and Write permissions

Set inquire and connect permissions

Go to your queue and right click and select manage authority records and give read and write permissions.

Manage authority records

set read and write permissions

Now we need to make these users trust each others ( XXXX\herath and WMQSERVER\bobmquser ). To do that we are going to user self-signed certificates.

So in this case we need to create key repositories. I am going to use C# console application to put message. Therefore I’m going to use “CMS” type key repositories.

Therefore i creat one key database for IBM MQ Server (192.168.10.2) WMQSERVER\bobmquser in following path (path doesn’t matter) D:\WebsphereKeyRepositary\AMSKeyStore\key.kdb and self-signed certificate for bobmquser

bobmquser's certificate

bobmquser’s certificate

repeat for the XXXX\herath ( 192.168.10.1). Key repository file path :- D:\AMSKeyRepo\key.kdb (path doesn’t matter, you can create this *.kdb file where ever you want )

Herath's certificate

Herath’s certificate

After creating these self-signed certificates . You need to generate *.arm file of each certificate. Then export certificates into each others key.kdb. You can use IBM Key management tool to exchange them. If you want to know how to exchange self-singed certificates please go through my “Exchanging self-signed certificates ” part in Transport level security with IBM WebSphere MQ in .net environment post.

To enable message security we need to create client keystore and server keystore in thier respective .mqs folders in thier %homepath%. You can use mkdir command in CMD to create .mqs folder.

Client's keystore

Client’s keystore

server's keystore

server’s keystore

Now we need to add a security policy which decides how to sign and encrypt message with self-signed certificates’ keys

Security Policy

Security Policy

So time to test our message security

using IBM.WMQ;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WebsphereMQ
{
    public class MessageProcess
    {

        const String connectionType = IBM.WMQ.MQC.TRANSPORT_MQSERIES_CLIENT;
        const String qManager = "QM_AMSTest";
        const String hostName = "192.168.10.2";
        const String channel = "ABC";
        const String port = "1501";

        MQQueue mqQueue; MQMessage mqMsg; MQGetMessageOptions mqGetMsgOpts;

        public Hashtable init()
        {
            Hashtable properties = new Hashtable();
            properties.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_CLIENT);
            properties.Add(MQC.HOST_NAME_PROPERTY, hostName);
            properties.Add(MQC.PORT_PROPERTY, port);
            properties.Add(MQC.CHANNEL_PROPERTY, channel);
            return properties;
        }

        public void RetrieveMessages()
        {
            try
            {
                Hashtable connectionProperties = init();
                MQQueueManager qMgr = new MQQueueManager(qManager, connectionProperties);
                mqQueue = qMgr.AccessQueue("XYZ", MQC.MQOO_INPUT_EXCLUSIVE | MQC.MQOO_FAIL_IF_QUIESCING);

                bool isContinue = true;
                int intRecordCounter = 1;

                while (isContinue)
                {

                    mqMsg = new MQMessage();
                    mqGetMsgOpts = new MQGetMessageOptions();

                    try
                    {
                        mqQueue.Get(mqMsg, mqGetMsgOpts);
                        var format = mqMsg.Format;
                        string message = mqMsg.ReadString(mqMsg.MessageLength);

                        if (mqMsg.Format.CompareTo(MQC.MQFMT_STRING) == 0)
                        {
                            Console.WriteLine("\n " + intRecordCounter + ") " + message);
                        }
                        else
                        {
                            Console.WriteLine("\n Non-text message");
                        }

                        // Counter Variable
                        intRecordCounter = intRecordCounter + 1;
                    }
                    catch (MQException mqe)
                    {
                        if (mqe.ReasonCode == 2033)
                        {
                            Console.WriteLine("No message available");
                        }
                        else
                        {
                            Console.WriteLine("MQException caught: {0} - {1}", mqe.ReasonCode, mqe.Message);
                        }

                        break;
                    }
                }

                Console.WriteLine("Read completed. Close the window");
                Console.ReadLine();

            }
            catch (MQException ex)
            {
                Console.WriteLine("WebSphere MQ error occurred: {0}", ex.ToString());
            }
            catch (System.Exception ex)
            {
                Console.WriteLine("System error occurred: {0}", ex.ToString());
            }

        }

        public void PutMessage()
        {
            try
            {
                Hashtable connectionProperties = init();
                MQQueueManager qMgr = new MQQueueManager(qManager, connectionProperties);
                MQQueue queue1 = qMgr.AccessQueue("XYZ", MQC.MQOO_OUTPUT | MQC.MQOO_FAIL_IF_QUIESCING);

                for (int i = 0; i < 5; i++)
                {
                    MQMessage msg = new MQMessage();
                    msg.Format = MQC.MQFMT_STRING;
                    msg.Encoding = 1208;
                    msg.Persistence = MQC.MQPER_PERSISTENT;
                    msg.CharacterSet = 1208;
                    msg.WriteString("Test Message " + i.ToString());
                    queue1.Put(msg);

                }

                Console.WriteLine("Write completed. Close the window");
            }
            catch (MQException ex)
            {
                Console.WriteLine("WebSphere MQ error occurred: {0}", ex.ToString());
            }
            catch (System.Exception ex)
            {
                Console.WriteLine("System error occurred: {0}", ex.ToString());
            }
        }
    }
}

Call the PutMessage() method from your Main method and run this application in your client machine. In my case I need to run this in XXXX\herath (192.168.10.1) pc. So it will put 5 messages at a time.

Messages in Alias queue

Messages in Alias queue

You can view these messages from alias queue and here it is with data encryption. So if bobmquser wants to retrieve these , Then go to the MQ server installation (see the CMD title bar ) and find the amqsget.exe  and execute like following image.

amqsget.exe

amqsget.exe

Remarks :-

  • When you insert message use WriteString() and if you use WriteUTF then when you retrieve messages it will come with some extra characters.
  • When you put messages in to queue, set the charset code ex:- 1208 for UTF-8

 

This entry was posted in C#, IBM WebSphere MQ. Bookmark the permalink.

1 Response to Advanced Message Security with IBM WebSphere MQ

Leave a comment