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.
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
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.
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.