IBM MQ user authentication
An IBM MQ queue manager can be configured to authenticate connecting users. But it does not keep a list of users or their passwords. That is the functionality that MQ leaves to external resources. There are two options you can choose from:
- Authenticate using the operating system
- Authenticate using a Lightweight Directory Access Protocol (LDAP)
In this post, we’ll talk about both of them. Some parameters are common to both of these methods and they are described in this section.
ADOPTCTX – whether or not to adopt context
MQ clients send user IDs and passwords for authentication using a data structure called MQCSP (MQ connection security parameters).
It is usually filled out in the code programmatically if you have a custom client or on a configuration page if you have a vendor application (like WebSphere Application Server, for example).
There is another user ID that MQ clients send to the server and it is distinct from what is being sent in MQCSP. That user ID is the user ID under which the client application is running.
Suppose you login to your Linux box with your personal user ID: mike123, then you compile your Java MQ app using javac, and then run it using JRE. In the application you fill out a hash table with MQ connection parameters, among which there is a service account user ID and password for your application which is authorized to access the objects on the queue manager you’re connecting to. That service account user ID is app456.
The queue manager will receive both of those: mike123 and app456. It will use app456 for authentication (its password will be checked), but the next step will be determined by the ADOPTCTX setting.
If it is set to YES, the user ID in MQCSP will be used for authorization checks, shown on displays, and appear in messages (this will be the user that puts and gets messages or does pub/sub). Queue manager will adopt this user ID only after it successfully authenticates.
If it is set to NO, the user ID the application is running under will be used for authorization checks and further down the road.
Note that authentication is ALWAYS performed on the MQCSP user ID and password pair. (Note: this was changed in MQ v9.1 and above. See my post about ChlauthEarlyAdopt and AdoptContext in 9.1+).
A more complicated example needs to be shown here for .NET applications. On Windows, applications run under user IDs that are logged onto the machine. You can change that by setting up your application to run as a service in which case it will run under a service account or using the “Run as …” option. In order to send a user ID and password in MQCSP, you need to use a .NET technique called impersonation.
Another note to make here is that Linux does not know what a Windows domain is, is case-sensitive when it comes to user IDs and only checks the first 12 symbols of the user ID. So Windows Administrator, ADMINISTRATOR and administrator accounts (all the same on Windows) become Administrato, ADMINISTRATO, and administrato (all distinct on Linux).
CHCKCLNT – whether to authenticate client connections and how to do it
A client connection is always made over a channel. A local connection is made in bindings mode by binding directly to server libraries. An MQ Explorer connection to a remote queue manager is a client connection (a connection to a Windows queue manager on the same machine is a local connection). A runmqsc connection is a local connection (a connection using a -c parameter is a client connection).
NONE – No user ID and password checks are made. If any user ID or password is supplied by a client application, the credentials are ignored. Basically, no authentication is done by MQ.
OPTIONAL – Client applications are not required to provide a user ID and password. Any applications that do provide a user ID and password in the MQCSP structure have them authenticated by the queue manager. The connection is only allowed to continue if the user ID and password are valid. I talked about this setting in the previous blog post. This CHCKCLNT setting is the global setting at the queue manager level. This setting is the default behavior, but it can be overwritten by a channel authentication record on each channel. If you anticipate there are applications in your infrastructure that won’t be able to pass a user ID and password (legacy applications, vendor applications with support for old MQ versions, custom code that nobody will touch), you can set CHCKCLNT to OPTIONAL here, set CHCKCLNT to ASQMGR on the channels for apps that can’t pass a user ID and password, and set CHCKCLNT to REQUIRED on the channels for those applications that can send a user ID and password.
REQUIRED – All client applications must provide a user ID and password in the MQCSP structure. This user ID and password is authenticated by the queue manager.
The connection will only be allowed to continue if the user ID and password are valid.
REQDADM – All client applications using a privileged user ID (such as mqm) must provide a user ID and password in the MQCSP structure. Any applications using a non-privileged user ID are not required to provide a user ID and password and are treated as with the OPTIONAL setting.
Any provided user ID and password are authenticated by the queue manager. The connection is only allowed to continue if the user ID and password are valid.
Not all combinations of CHCKCLNT on the queue manager level and CHCKCLNT on the channel level are possible. One notable exception is setting CHCKCLNT to NONE on the queue manager and setting CHCKCLNT to REQUIRED on the channel. Such a connection will fail with AMQ9793.
CHCKLOCL – whether to check local connections
A local connection happens in bindings mode and does not involve a channel. For example, when you login to the box where the queue manager is running and type “runmqsc” in the terminal window, you’re making a local connection.
NONE – No user ID and password checks are made. If any user ID or password is supplied by a locally bound application, the credentials are ignored.
OPTIONAL – Locally bound applications are not required to provide a user ID and password. Any applications that do provide a user ID and password in the MQCSP structure have them authenticated by the queue manager. The connection is only allowed to continue if the user ID and password are valid.
REQUIRED – All locally bound applications must provide a user ID and password in the MQCSP structure. This user ID and password will be authenticated by the queue manager. The connection will only be allowed to continue if the user ID and password are valid.
REQDADM – All locally bound applications using a privileged user ID must provide a user ID and password in the MQCSP structure. Any locally bound applications using a non-privileged user ID are not required to provide a user ID and password and are treated as with the OPTIONAL setting.
Any provided user ID and password will be authenticated by the queue manager. The connection will only be allowed to continue if the user ID and password are valid.
Example: you set CHCKLOCL to REQUIRED, then you type “runmqsc MYQMGR”. You will get an error, because you need to authenticate for a local connection. To do that, run the command: “runmqsc MYQMGR -u <user ID>”. You will be prompted for password. Note that if you use the -c flag, your connection will become a client connection and the queue manager will check the setting in CHCKCLNT instead.
FAILDLAY – fail delay time
When a user ID and password are provided for connection authentication, and the authentication fails due to the user ID or password being incorrect, this is the delay, in seconds, before the failure is returned to the application. This can aid in avoiding busy loops from an application that simply retries, continuously, after receiving a failure. The value must be in the range 0 – 60 seconds. The default value is 1.
Authenticate using the operating system
This is the default method of authentication and later versions of MQ come pre-configured for this type of authentication out of the box since MQ v8 (when you create a queue manager). The command to create an authentication object is:
DEFINE AUTHINFO(name) AUTHTYPE(IDPWOS)
ADOPTCTX(NO|YES)
CHCKCLNT(OPTIONAL|REQDADM|NONE|REQUIRED)
CHCKLOCL(OPTIONAL|REQDADM|NONE|REQUIRED)
FAILDLAY(1|integer)
Description of parameters follows.
name – name of the authentication object
AUTHTYPE(IDPWOS) – authentication type is “user ID and password are checked by the operating system”.
ADOPTCTX, CHCKCLNT, CHCKLOCL, and FAILDLAY parameters are described above.
The default object created and enabled on the new queue managers is configured as follows:
AUTHINFO(SYSTEM.DEFAULT.AUTHINFO.IDPWOS) AUTHTYPE(IDPWOS) ADOPTCTX(NO)
CHCKCLNT(REQDADM) CHCKLOCL(OPTIONAL) FAILDLAY(1)
Authenticate using LDAP
Next, we will look at the LDAP authentication method. Most of these parameters will be very familiar to LDAP servers’ administrators. If you can enlist their help, do so. MQ supports authenticating in any software product that adheres to LDAP v2 or v3 protocols (MS AD, IBM Tivoli, UNIX LDAP, Centrify, etc.)
I will use the following two examples to illustrate. The examples are based on a UNIX LDAP configuration from a real project:
Group entry in UNIX LDAP:
dn: cn=mq_users,ou=Group,dc=unix,dc=org,dc=com
memberUid: mq_user
memberUid: mike670
memberUid: jill588
memberUid: sam025
objectClass: posixGroup
objectClass: top
cn: mq_users
User entry in UNIX LDAP:
dn: uid=mik123,ou=People,dc=unix,dc=org,dc=com
memberOfNetgroup: cn=auth_group1,ou=Netgroup,dc=unix,dc=org,dc=com
memberOfNetgroup: cn=sudo_group2,ou=Netgroup,dc=unix,dc=org,dc=com
memberOfNetgroupShortName: auth_group1
memberOfNetgroupShortName: sudo_group2
memberOf: cn=mike123,ou=Group,dc=unix,dc=org,dc=com
memberOf: cn=mq_users,ou=Group,dc=unix,dc=org,dc=com
memberOfShortName: mike123
memberOfShortName: mq_users
objectClass: top
objectClass: person
objectClass: inetorgperson
objectClass: inetUser
objectClass: organizationalPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: mike123
The command to create an authentication object is:
DEFINE AUTHINFO(name) AUTHTYPE(IDPWLDAP)
ADOPTCTX(NO|YES)
AUTHORMD(OS|SEARCHGRP|SEARCHUSR|SRCHGRPSN)
BASEDNG(string) BASEDNU(‘ ‘|string)
CLASSGRP(string) CLASSUSR(‘inetOrgPerson’|string)
GRPFIELD(string) USRFIELD(‘ ‘|string)
FINDGRP(string) NESTGRP(YES|NO) SHORTUSR(string)
CHCKCLNT(REQDADM|NONE|OPTIONAL|REQUIRED)
CHCKLOCL(REQDADM|NONE|OPTIONAL|REQUIRED)
FAILDLAY(1|integer)
CONNAME(string) LDAPPWD(‘ ‘|string) LDAPUSER(‘ ‘|string) SECCOMM(NO|YES|ANON)
Description of parameters follows.
name – name for this authentication object
AUTHTYPE(IDPWLDAP) – user ID and password will be sent to LDAP for authentication. Note that MQ does not check anything, it receives a response from the LDAP server.
ADOPTCTX – described above.
AUTHORMD – Authorization Method. This parameter tells the LDAP server how it should look for the user MQ is sending.
OS – Use operating system groups to determine permissions associated with a user. This is how IBM MQ has previously worked, and is the default value.
SEARCHGRP – A group entry in the LDAP repository contains an attribute listing the Distinguished Name of all the users belonging to that group. Membership is indicated by the attribute defined in FINDGRP. This value is typically member or uniqueMember. As you can see in our group entry example above, FINDGRP value will be “memberUid”.
SEARCHUSR – A user entry in the LDAP repository contains an attribute listing the Distinguished Name of all the groups to which the specified user belongs. The attribute to query is defined by the FINDGRP value, typically memberOf. In our user entry example above, FINDGRP will be memberOf. As you can see, a user can be a member of two types of groups: a NetGroup and a posixGroup (or just called Group). In this example, we want to check if a user is in the group mq_users, and all groups created for MQ membership are created as posixGroups, so we use “memberOf”. Were we checking membership in a NetGroup (highly unlikely in a real world scenario), we would’ve used “memberOfNetgroup” as FINDGRP.
SRCHGRPSN – 9.1.0 only. A group entry in the LDAP repository contains an attribute listing the short user name of all the users belonging to that group. The attribute in the user record that contains the short user name is specified by SHORTUSR. Membership is indicated by the attribute defined in FINDGRP. This value is typically memberUid. This authorization method should only be used if all user short names are distinct.
A short user name is just the user name without the qualifier. It is different from the distinguished name (DN) which is fully qualified and, therefore, unique. Looking at our example for group entry, we see that short user names are located in “memberUid” field. Our example doesn’t have a field for DNs of users. This type of setup can actually be valid, given that all short user IDs are distinct. SHORTUSR field value in our user example would be “uid”.
Many LDAP servers use an attribute of the group object to determine group membership and you should, therefore, set this value to SEARCHGRP. Microsoft Active Directory typically stores group memberships as a user attribute. The IBM Tivoli Directory Server supports both methods. In general, retrieving memberships through a user attribute will be faster than searching for groups that list the user as a member.
BASEDNG – Base DN for groups. DN is the distinguished name. It consists of common name (cn), followed by the entire hierarchy of objects, like cn=…, ou=…, dc=…, dc=…, dc=… In order to be able to find group names, this parameter must be set with the base DN to search for groups in the LDAP server. Looking at our our example above, we search for dn: and see that the base is “ou=Group,dc=unix,dc=org,dc=com”
BASEDNU – base DN for users. In order to be able to find the short user name attribute (see SHORTUSR ) this parameter must be set with the base DN to search for users within the LDAP server. In our example above, look for dn: and you’ll see that the base DN is clearly “ou=People,dc=unix,dc=org,dc=com”
CLASSGRP – The LDAP object class used for group records in the LDAP repository.
In addition to DN, each object in LDAP has a class, which represents the level at which the object exists in the LDAP hierarchy. If we look at our group example above we can clearly see that the top class of the hierarchy is “top” and our group object is right below it in class “posixGroup”. Other commonly used values include groupOfUniqueNames or group. If the value is blank, groupOfNames is used.
CLASSUSR – The LDAP object class used for user records in the LDAP repository. Look at our example above and notice that the user hierarchy starts at class “top” and goes down to class “shadowAccount”. Because these examples are from real life, it was determined by trial and error that the correct class for users is “inetorgperson” and not “shadowAccount”. If blank, the value defaults to inetOrgPerson, which is generally the value needed. For Microsoft Active Directory, the value you require is often user.
GRPFIELD – LDAP attribute that represents a simple name for the group.
If the value is blank, commands like setmqaut must use a qualified name for the group. The value can either be a full DN, or a single attribute. Our example above shows that GRPFIELD for a posixGroup is “cn”.
USRFIELD – LDAP attribute that represents a simple name for the user. If the user ID provided by an application for authentication does not contain a qualifier for the field in the LDAP user record, that is, it does not contain an equals (=) sign, this attribute identifies the field in the LDAP user record that is used to interpret the provided user ID. This field can be blank. If this is the case, any unqualified user IDs use the SHORTUSR parameter to interpret the provided user ID. The contents of this field will be concatenated with an ‘ = ‘ sign, together with the value provided by the application, to form the full user ID to be located in an LDAP user record. For example, the application provides a user of fred and this field has the value cn, then the LDAP repository will be searched for cn=fred. In our example, it’s “uid” again.
FINDGRP – Name of the attribute used within an LDAP entry to determine group membership.
When AUTHORMD = SEARCHGRP, the FINDGRP attribute is typically set to member or uniqueMember.
When AUTHORMD = SEARCHUSR, the FINDGRP attribute is typically set to memberOf.
9.1.0 only – When AUTHORMD = SRCHGRPSN, the FINDGRP attribute is typically set to memberUid.
When the FINDGRP attribute is left blank:
If AUTHORMD = SEARCHGRP, the FINDGRP attribute defaults to memberOf.
If AUTHORMD = SEARCHUSR, the FINDGRP attribute defaults to member.
9.1.0 only – If AUTHORMD = SRCHGRPSN, the FINDGRP attribute defaults to memberUid.
NESTGRP – Group nesting.
NO – Only the initially discovered groups are considered for authorization.
YES – The group list is searched recursively to enumerate all the groups to which a user belongs.
The group’s Distinguished Name is used when searching the group list recursively, regardless of the authorization method selected in AUTHORMD.
This setting determines if you want to allow permissions to be nested inside each other.
Example:
mq_admins group contains three users that can create create and delete queue managers.
mq_support group contains four users that can change queues attributes. It also contains groups mq_admins which means that the three users in mq_admins also get permissions from mq_support.
mq_users group has permissions to browse messages. Plus it contains the mq_support group.
This setup allows users in mq_users to browse only, users in mq_support to browse and change queue attributes, and users in mq_admins have permissions to browse, change queue attributes and create and delete queue managers.
SHORTUSR – A field in the user record to be used as a short user name in IBM MQ.
This field must contain values of 12 characters or less. This short user name is used for the following purposes:
If LDAP authentication is enabled, but LDAP authorization is not enabled, this is used as an operating system user ID for authorization checks. In this case, the attribute must represent an operating system user ID.
If LDAP authentication and authorization are both enabled, this is used as the user ID carried with the message in order for the LDAP user name to be rediscovered when the user ID inside the message needs to be used.
For example, on another queue manager, or when writing report messages. In this case, the attribute does not need to represent an operating system user ID, but must be a unique string. An employee serial number is an example of a good attribute for this purpose.
In our example this field needs to be set to “uid”.
CHCKCLNT, CHCKLOCL, and FAILDLAY parameters are described above.
Note that REQDADM value for the CHCKCLNT attribute is irrelevant if the authentication type is LDAP. This is because there is no concept of privileged user ID when using LDAP user accounts. LDAP user accounts and groups must be assigned permission explicitly.
CONNAME – The host name, IPv4 dotted decimal address, or IPv6 hexadecimal notation of the host on which the LDAP server is running, with an optional port number. If you specify the connection name as an IPv6 address, only systems with an IPv6 stack are able to resolve this address.
The syntax for CONNAME is the same as for channels. For example, conname(‘ hostname (nnn)’) where nnn is the port number. On UNIX, Linux, and Windows, the maximum length is 264 characters. This can also be a comma separated list of connection names (if you have more than one LDAP server running).
Note that unsecure LDAP protocol is traditionally setup on port 356, and secure LDAP is setup on port 636.
LDAPPWD – The password associated with the Distinguished Name of the user who is accessing the LDAP server. Its maximum size is 32 characters.
LDAPUSER – The Distinguished Name of the user who is accessing the LDAP server. The maximum size for the user name is 1024 characters
SECCOMM – Whether connectivity to the LDAP server should be done securely using TLS
YES – Connectivity to the LDAP server is made securely using TLS.
The certificate used is the default certificate for the queue manager, named in CERTLABL on the queue manager object, or if that is blank, the one described in Digital certificate labels. The certificate is located in the key repository specified in SSLKEYR on the queue manager object. A cipherspec will be negotiated that is supported by both IBM MQ and the LDAP server. If the queue manager is configured to use SSLFIPS(YES) or SUITEB cipher specs, then this is taken account of in the connection to the LDAP server as well.
ANON – Connectivity to the LDAP server is made securely using TLS just as for SECCOMM(YES) with one difference.
No certificate is sent to the LDAP server; the connection will be made anonymously. To use this setting, ensure that the key repository specified in SSLKEYR, on the queue manager object, does not contain a certificate marked as the default.
NO – Connectivity to the LDAP server does not use TLS.
Summing up all the parameters this would be the command for the LDAP examples we used in this exercise:
DEFINE AUTHINFO(QMGR1.IDPW.LDAP) AUTHTYPE(IDPWLDAP) CONNAME(‘ldap-server1.org.com(636),ldap-server2.org.com(636),ldap-server3.org.com(636)’) SHORTUSR(‘uid’) ADOPTCTX(YES) AUTHORMD(SEARCHUSR) BASEDNG(‘ou=Group,dc=unix,dc=org,dc=com’) BASEDNU(‘ou=People,dc=unix,dc=org,dc=com’) CHCKCLNT(OPTIONAL) CHCKLOCL(NONE) CLASSGRP(‘posixGroup’) CLASSUSR(‘inetorgperson’) FINDGRP(‘memberOf’) GRPFIELD(‘cn’) LDAPPWD(‘ldap_password’) LDAPUSER(‘cn=ldap_user,dc=unix,dc=org,dc=com’) NESTGRP(YES) SECCOMM(YES) USRFIELD(‘uid’)
ALTER QMGR CONNAUTH(QMGR1.IDPW.LDAP)
After running the DEFINE AUTHINFO command, you must restart the queue manager. If you do not restart the queue manager, the setmqaut command does not return the correct result. Restarting the queue manager will also refresh security of type connauth.
One last note: by default MQCSP structures (including the user ID and password stored in them) are sent across the network in the clear (not encrypted). Therefore, you should use an IBM-devised mechanism for protecting MQCSP (subject for another blog post) or protect your client connections with TLS.
Let me know in comments if these instructions were helpful to you at all in your everyday work!
For more on working with MQ Channel Authentication Records, click here.
Really helpful, thank you
This is really helpful.
But I am stuck at one place.
We enabled LDAP successfully, with CHCKCLNT = OPTIONAL. Application connecting with SVRCONN channel are connecting without issue.
But We receive message from RCVR channel are failing with 2035 and going to DEADQ, after LDAP is enabled. Reply To Queue, is failing.
Message received by RCVR channel, carry an ID in Message Heard. Same ID is created locally on server, but not in LDAP server. We though that’s not required, because on RCVR channel MCAUSER is ‘blank/empty’. But now this doesn’t wor,
If we disable LDAP, configuration start working.