Controlling queue creation

padlock

A recent thread on mqseries.net asked about controlling queue creation in MQ. In particular, how to set authorities so that one user can create queues like “ABC…” but not “DEF…”. There are answers given in that thread both on the ability to do it, and the reason why it’s not usually something that’s needed.

In summary, it’s not possible to control it with setmqaut commands. And since queue creation is usually done by administrators, there’s not really any need to restrict it further.

But the thread did remind me of some code I’d written a few years ago while considering the same question as part of a larger piece of work. And so I thought I’d dredge up that PoC and make it a bit more readable. It shows how you can, in fact, implement that level of control on platforms where you can install extensions to the MQ Authorisation interface.

Normal controls

Usually, the control of whether someone can create an object is stored as a “global” permission for the object type as part of a special object called @class. There is one @class object for each object type – queue, channel, namelist etc. And when you run dmpmqaut you can see these permissions:

$ dmpmqaut -m QM1 -n @class
profile:     @class
object type: rqmname
entity:      metaylor
entity type: group
authority:   none
- - - - - 
profile:     @class
object type: queue
entity:      metaylor
entity type: group
authority:   crt

Extended controls

These permissions are applied and checked by MQ’s Object Authority Manager. But that is a pluggable service. If you don’t like what it does, it is possible to augment or replace it by your own implementation. Many years ago I wrote a SupportPac (now on github) that logs the authorisation operations made by the queue manager. It was a way of debugging what goes on and documenting how you can write an alternative.

I used that package while looking into this question to record what happens when a user creates a queue, either explicitly or – by opening a MODEL queue where you can programmatically define a prefix for the dynamic queue – implicitly. After seeing how the authorisation checks are made, I wrote an extension that gets ahead of the regular OAM and makes its own decision on whether the operation can proceed.

So when running DEFINE QLOCAL(Z), the logging module showed the queue manager making this call:

[28966972.2828 @ Wed Oct 13 09:12:40 2021] OACheckAuth
    Object : "Z " [Queue]
    User : "metaylor"
    Auth : 0x00010000 [crt ]

which is very simple to recognise and intercept. Handling dynamic queues has a more complex pattern, involving a sequence of OAM calls, but it is still a pattern that can be recognised. Note that the authorisation check is always based on a username’s permission, regardless of whether you are using a user or group-based authorisation configuration.

The oamcrt Installable Service

The module I wrote sits as a new Installable Service ahead of the regular OAM in a chain of modules. You can find the source as oamcrt alongside the oamlog module in the MQ Exits Repository that I wrote more about here.

This service is not very intelligent, but it is good enough to demonstrate the principles. The main (admittedly severe) limitation is that it has a hardcoded pattern for rejection of object creation. In any productised version, there would be some kind of external configuration file with pattern matching abilities. I’ve tried to show where reading the file and doing checks against its contents would fit. And I’ve also showed how the process/thread models within the queue manager would work with essential locking. But the configuration part seemed to be code that was “well understood” whereas I was interested in the MQ Authorisation processing piece of the puzzle.

This module simply rejects any attempt to create a queue whose name starts with NOTALLOWED, even when administrators do it:

Starting MQSC for queue manager OAMLOG.
1 : DEF QL(NOTALLOWED.1) REPLACE
AMQ8135E: Not authorized.
One valid MQSC command could not be processed.

The amqsput sample program, which allows you to nominate the prefix of a dynamic queue similarly fails. (The repository has a slightly-modified version of amqsput included. It just makes it a bit easier to use default values for some of the arguments, but is otherwise the same as the standard sample.)

$ bin/sput SYSTEM.DEFAULT.MODEL.QUEUE OAMLOG -1 -1 _ NOTALLOWED
Sample AMQSPUT0 start
target queue is SYSTEM.DEFAULT.MODEL.QUEUE
dynamic queue name is NOTALLOWED
MQOPEN ended with reason code 2035
unable to open queue for output

If this module decides to reject a request, that is the end of that flow – the regular OAM cannot override the decision. If this module permits a request, then the OAM still gets the opportunity to see whether it likes the command.

Possible enhancements

Clearly we could enhance this module to actually process a configuration file. And it could include other object types beyond queues. But hopefully this gives an interesting demonstration of what you can achieve with the extensibility of one of MQ’s lesser-known interfaces.

Leave a Reply

Your email address will not be published. Required fields are marked *