Using LDAP with MQ multiplatform and nested groups.

This blog post follows on from Using LDAP with multi platform.

Nested groups can be used to simplify administration

It is good practice to grant authority to access resources using groups, rather than giving access to individual userids. For example if an application uses 10 queues, and a new person joins the team you can either connect the new id to one group, or give the id access to the 10 queues.

Using nested groups takes this further. Imagine the payroll queues are managed by the GRPAYROLL access group, the HR queues managed by the GRHR access group, and the Finance queue managed by the GRFINANCE access group. The MQ system programmers can manage any queue. You could give GRMQADMIN access to the Payroll queues, HR queues, and Finance queues. Or you say the GRMQADMIN is the super set and includes a reference to GRPAYROLL, GRHR, and GRFINANCE. If you define a HR queue, you just give GRHR access to it, and the MQ Administration team get access to it “for free”.

You can take this further, and have a group GRHR_GR1, and GRHR_GR2 which give access to a subset of HR queues. The GRHR group could include both of these.

The model of this is a tree where a group high up in the tree incorporates the groups lower down the tree.

There are two ways of defining groups in LDAP.

1. Define a group record, and list the members of the group. This is called a static group

dn:cn=GR1,OU=groups,o=myorg
member:cn=user1,ou=users,o=myorg
member:cn=user2,ou=users,o=myorg

To retrieve the groups for a user, you issue a query for all groups which have the given member data.

2. Specify the group name as part of the user’s record, this is known as a dynamic group.

dn=cn=user1,ou=users,o=myorg
group=cn=group1,ou=groups,o=myorg
group=cn=group2,ou=groups,o=myorg

For this you retrieve the “group” attributes from the record. Note: The group attribute does not exist in LDAP, you have to use a different one ( I used the st attribute).

Nested group support.

There is an MQ AUTHINFO parameter NESTGRP. The documentation says

  • NESTGRP Group nesting.
    • YES The group list is searched recursively to enumerate all the groups to which a user belongs.

Static groups and nested group support.

My MQ ADUTHINFO had


AUTHORMD(SEARCHGRP) +
BASEDNG(‘ou=groups,o=your Company’) +
CLASSGRP(‘groupOfNames’) +
GRPFIELD(sn) +
FINDGRP(‘member’) +
NESTGRP(yes) +

On my system the userid ibmuser is a “member” of two groups mqstatic and mqstatic2

dn: cn=mqstatic,ou=groups,o=your Company
objectclass: groupOfNames
cn: mqstatic
ou:groups.
member: cn=ibmuser,o=your Company
member: cn=adcdb,o=your Company

and

dn: cn=mqstatic2,ou=groups,o=your Company
objectclass: groupOfNames
cn: mqstatic2
ou:groups.
member: cn=ibmuser,o=your Company

There is another group, which refers to the mqstatic group.

dn: cn=mega,ou=groups,o=your Company
objectclass: groupOfNames
cn: mega
ou:groups.
member: cn=mqstatic,ou=groups,o=your Company
member: cn=gg,ou=groups,o=your Company

As part of the userid to group mapping, MQ issues the query What groups have member: cn=ibmuser,o=your Company. The response is

  • dn: cn=mqstatic2,ou=groups,o=your Company
  • dn: cn=mqstatic,ou=groups,o=your Company

When NESTGRP(YES) is specified MQ then queries all groups that have cn=mqstatic2,ou=groups,o=your Company, and does another query for dn: cn=mqstatic,ou=groups,o=your Company

and gets the response dn: cn=mega,ou=groups,o=your Company.

The cn=ibmuser is associated with the three groups, and those three groups are used for access checking.

For a data model I see it as

dn=cn=GRHR_GR1
isusedby: CN=GRHR

and

dn:cn=GRHR
isusedby: CN=MQADMIN

and

dn: cn=mqadmin
member:cn=user1

The “isusedby” attribute name, is in reality “member”, which I feel is very confusing, as member implies membership, and there is no membership involved. This is an LDAP naming problem – not MQ’s.

This model feels upside down (or inside out) (or both). It takes several cups of tea with biscuits to draw up the groups and the connections definitions you need. Put the kettle on, and try defining the groups for the MQADMIN, GRFINANCE, and GRFINANCEGR1, GRFINANCEGR2 groups; three people in MQADMIN, and two people in finance; then add a definition for GRFINANCEGRN.

Using dynamic groups and nested group support

This feels more the right way up – but it is upside down compared to static groups.

My authinfo had

AUTHORMD(SEARCHUSR) +
FINDGRP(‘st’) +
BASEDNU(‘o=Your Company’) +
CLASSGRP(‘person’) +

With my userid I had

dn: cn=user1, o=Your Company
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: ibm-nativeAuthentication
objectclass: inetOrgPerson
departmentNumber: mqadmin
cn: ibmuser
sn: ibmuser
ou: test
st: cn=group,ou=groups,o=your Company
st: cn=mqadmin,ou=groups,o=your Company
ibm-nativeId: ibmuser

Where st: defined the groups.

For the entry for cn=group, I defined a nested group called cn=deepergroup.

dn: cn=group,ou=groups,o=your Company
objectclass: top
objectclass: person
objectclass: organizationalPerson
cn: cpgroup
ou: groups
st : cn=deepergroup,o=your Company
sn : groupgroup

You need an entry for cn=deepergroup… in LDAP

dn: cn=deepergroupou=groups,o=your Company
objectclass: person
cn: mega
sn:mega

# no st attribute, so there is no more nesting

I define the cn=mqadmin group to LDAP with no “sn” entry, because it has no nesting.

MQ issues a query to LDAP asking for the group definitions ( st in my case) for the given user. For each group that gets returned, query that group for any more group (st in my case) definitions, etc.

Together these give three groups for the cn=ibmuser:

  • cn=mqadmin,ou=groups,o=your Company
  • cn=deepergroup,ou=groups,o=your Company
  • cn=group,ou=groups,o=your Company

Dynamic group data model

The data model for dynamic group feels more natural, where the “is in” and “includes” are the attribute you chose, “st” in my case.

  • dn=cn=user1
    • is in: cn=group1…
  • dn=cn=group1…
    • includes: cn=groupdeep

Enabling nestgrp(yes) with dynamic groups may throw errors

If you start with

dn=cn=user1,…
group=cn=group1,..
group=cn=group2,…

With nestgrp(no) this defines the userid is in two groups.

If you enable nestgrp(yes) then when the user id is used, MQ checks there are entries in LDAP for group=cn=group1,.. and group=cn=group2,… If the definitions do not exist, you get the MQ message:

AMQ5532E: Error authorizing entity in LDAP

EXPLANATION:
The LDAP authorization service has failed in the ldap_first_entry call while trying to find user or group ‘NULL’. Returned count is 0. Additional context is ‘cn=group1,… ‘.

To solve the problem I defined the two groups to LDAP.

For group1 I defined

dn:cn=group1,…
group:cn=deepergroup…

and I defined the deepergroup group (to keep mq happy) with no group entries (to indicate end of the nesting).

dn:cn=deepergroup,…

One thought on “Using LDAP with MQ multiplatform and nested groups.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s