How to remove MQ authorities for deleted ids

padlock

A userid or group deleted from the operating system still shows up in a queue manager’s authority lists. Ideally you would have removed those authorisations before deleting the id, but if you have not, then MQ will not usually let you delete the authorisations later. This post explains the procedure that I use to remove MQ authorities for deleted ids or to cold-start the authorisations when testing. I’ll also describe a second procedure that you might prefer.

There are both use-at-own-risk methods, but I’ve given an outline a few times in posts and replies elsewhere. After a bit of encouragement, I finally decided it might be better to give fuller details so you can make a proper evaluation of whether to use the technique.

What is the problem

You have set MQ authorities for a user:

$ setmqaut -m QMAUT -t qmgr -p oldid +connect

The user leaves your organisation and is deleted from the operating system. You want to clean up the MQ pieces. But the setmqaut fails and the records are still there:

$ setmqaut -m QMAUT -t qmgr -p oldid -remove
AMQ7026E: A principal or group name was invalid.
$ dmpmqaut -m QMAUT -p oldid
 profile:     self
 object type: qmgr
 entity:      oldid
 entity type: principal
 authority:   connect
 
 profile:     @class
 object type: qmgr
 entity:      oldid
 entity type: principal
 authority:   none

My QMAUT queue manager is configured with SecurityPolicy=User to make it a bit simpler to generate some of these examples (no need to worry about primary group memberships) but the basic issue is the same if you are using the default “group” mode for a Unix queue manager, or even if you have configured the system to explicitly use an LDAP repository.

The usual recommendation

Ideally, the MQ administrator would be told in advance of removal from the directory, coordinating the process with security administrators. But we all understand the challenges there.

On Unix systems, or when using LDAP, the usual way to allow the setmqaut to complete is to temporarily reinstate the username. That requires another level of cooperation with security or directory admins.

On Windows, reinstatement doesn’t help because authorities are managed internally using a SID (Security Identifier) which are not reused even when a username is. But at least there is an option (-u) for setmqaut on Windows to remove the authority by SID. That SID option is however not available through the SET AUTHREC MQSC command or its PCF equivalent,

When you do a dmpmqaut on Windows, it usually shows the username. But if it cannot resolve the SID to a known id, then it displays the SID directly.

> dmpmqaut -m V92_W -t qmgr

 profile:     SELF
 object type: qmgr
 entity:      S-1-5-21-1504523420-1018
 entity type: unknown
 authority:   connect
 
 profile:     @CLASS
 object type: qmgr
 entity:      S-1-5-21-1504523420-1018
 entity type: unknown
 authority:   none

...

> setmqaut -m V92_W -t qmgr -u S-1-5-21-1504523420-1018 -remove
The setmqaut command completed successfully. 

The @class records

You can see in the above example that there is a profile called @CLASS. Essentially for every object type that a user is granted access to, there will be a corresponding @class record that holds information global to all objects of that particular type. Unfortunately, these records cannot be deleted using any command even if the user still exists – they are permanent once created. They don’t do any real harm as they would only take effect when someone is allowed to do other things with the queue manager such as connecting or accessing a queue. But they still look messy. The procedure I’m about to outline will also deal with these records.

How does MQ store authorities

The original MQ design stored information about authorisations in text files associated with each object. The files looked a bit like the qm.ini format – stanzas had information about each user or group, and their assigned authority to that object. One of the reasons for this simple design was that the authorisation component was pluggable and we expected more “hardened” security integration to be provided by third-party solutions. It’s a bit like how using the SAF interface on z/OS allows use of RACF or ACF2 or Top Secret.

But it became clear that no alternatives would appear. Once the requirement to handle wildcarded resources became more important, we needed something better. In MQ V5.2 the file format migrated to data held as messages on a queue. It gained not only more flexibility in the object names (wildcards) but also things like persistence and recoverability to the same degree as any other MQ message. There was no need to take a separate backup of the stanza files.

The queue SYSTEM.AUTH.DATA.QUEUE holds these messages. The queue manager has a little bit of special awareness of this queue because the security manager (the OAM) needs to access it before reading the authorisations. But after queue manager initialisation, it treats the queue just like any other. The OAM opens the queue for exclusive access to ensure no other process can modify its contents.So you couldn’t try something sneaky like working out which messages hold the records you want removed, and then running MQGET with a msgid/correlid to match those messages. And there are other reasons why that wouldn’t work, as the OAM rewrites the messages to match internal in-memory state.

UserExternal

MQ 9.2.1 brought a new feature for MQ on Unix platforms, called the UserExternal policy which I wrote about here. Can this help us? Up to a point. With a queue manager set with this policy, there is no requirement for a user to exist when authorities change. And that would include removing the authorisation records. But

  • It doesn’t help with group management, which would usually be the setting
  • It doesn’t help if your queue manager is using LDAP
  • It doesn’t help on Windows which doesn’t have this policy option
  • It doesn’t do anything to clean up the @class records

So not a great answer.

The cleanup procedure

With this background, I’m going to show how you can handle both unknown ids and the @class records. I’ll repeat that this is an at-your-own-risk unofficial process. And if you want to use it, I’d strongly recommend trying it out on an unimportant system first and second.

What I’m going to do is to completely replace the list of authorisations on a queue manager.

1. Take a copy of all existing authorisations for the queue manager. I’m going to use dmpmqcfg instead of dmpmqaut as it can create a replayable MQSC script.

$ dmpmqcfg -m QMAUT -x authrec >auths.txt

2. Check the output file has what you expect. Edit the file to remove all references to the users and groups that you want to delete. This should include removing those entities’ @class lines.

3. Create a new queue manager as part of the same installation as your real queue manager. This queue manager will not be needed for long and does not ever need to be started.

$ crtmqm TEMP

4. Find the operating system file corresponding to the queue where authorisations are stored. Copy that file to your working directory. Quotes may be needed around the filename as the mangled version with ! characters may get misinterpreted by your shell. Once you’ve done this, you can delete the temporary queue manager.

$ cp "/var/mqm/qmgrs/TEMP/queues/SYSTEM!AUTH!DATA!QUEUE" authQ
$ dltmqm TEMP

5. Stop the real queue manager so there is nothing using the OAM data. Copy that queue manager’s authorisation queue file in case you need to reverse this process.

$ endmqm -i QMAUT
$ cp "/var/mqm/qmgrs/QMAUT/queues/SYSTEM!AUTH!DATA!QUEUE" authQ.QMAUT.bak

6. Copy the saved empty queue file over the top of the “real” queue. If you are not running as the mqm id, then you may need to adjust the file privileges. Since I tend not to run as mqm, I used sudo. But this might be a rare instance where doing work as the real mqm id might simplify steps. It also might be easier to put these steps in a simple script to avoid retyping the long filename. This step gives the queue manager a replacement set of authorities; essentially it’s got only the basic list from the creation phase.

destFile="/var/mqm/qmgrs/QMAUT/queues/SYSTEM!AUTH!DATA!QUEUE"
ls -l $destFile # What does it look like now
 
cp authQ "$destFile"
sudo chown mqm:mqm "$destFile" # Logged in as mqm, won't need sudo
sudo chmod 660 "$destFile"     
ls -l $destFile                # Does it match

7. Start the queue manager and rebuild the authorisations from the edited copy. Make sure the runmqsc has completed successfully with no bad commands. If you have badly edited the replay script, you can stop the queue manager, redo step 6 and try again.

$ strmqm QMAUT
$ runmqsc QMAUT < auths.txt

8. Run dmpmqaut to check that you have just the authorisations you now expect.

9. If you’re using linear logging, it would be a good idea (thanks, Jon) to record a media image of the replacement authorisation queue. So that in the event of a crash, the queue manager doesn’t try to roll back to a previous image of the queue.

$ rcdmqimg -m QMAUT -t queue SYSTEM.AUTH.DATA.QUEUE

And that’s it.

This process should work on all the Distributed platforms, although things like the file locations and how the operating system permissions on that file are modified could be different. The principles still hold.

One concern I had when I started using this process was that the temporary queue manager does not have all the same objects (queues, channels etc) defined as the real queue manager. So the empty authorisation file won’t include anything about them, even for the mqm id. Would that affect the ability to use those objects? In practice, the queue manager seems to cope. When you are connected as a fully-authorised person (mqm group etc) then the OAM doesn’t need to look for associated records.

An alternative approach

I do have another way of doing this. I find it a little more cumbersome but does also appear to work and it does not involve messing with the queue files directly. Instead, we will temporarily disable all authorisation processing on the queue manager.

Steps 1 and 2 are the same as previously to get a backup of your current authorities and then edit them to the desired state.

3. Stop the queue manager

4. Edit the queue manager’s ini file to remove (comment out) both stanzas that refer to authorisation – the service and the specific service component. Don’t delete the lines as we will bring them back in a moment.

#Service:
#    Name=AuthorizationService
#    EntryPoints=14
#ServiceComponent:
#    Service=AuthorizationService
#    Name=MQSeries.UNIX.auth.service
#    Module=amqzfu
#    ComponentDataSize=0

5. Restart the queue manager. This is the point where you need to be certain that noone else will be trying to use the queue manager as they will have full authorities if they are able to connect. To reduce the chance of that happening use the startup mode that does not start things like the listener processes:

$ strmqm -ns QMAUT

6. Clear the authorisation queue using an MQ program.

$ amqsget SYSTEM.AUTH.DATA.QUEUE QMAUT

You can do it this time because the OAM is not loaded, so there is nothing holding exclusive access to the queue. And there will be nothing to overwrite your changes with any cached data.

7. Stop the queue manager, reinstate the lines in qm.ini and restart it normally. Authorisation processing is now back in place.

8. Use the edited list of authorisations as input to runmqsc.

9. Use dmpmqaut to check that you have just the authorisations you now expect.

Will MQ ever implement this more directly?

There is already an Idea/RFE that you can vote on for a simpler solution. It can be found here. It’s been accepted as something we would like to do, but there’s no guarantee on if or when it might appear. And even if it does get done, that wouldn’t help all the older installations.

Summary

I’ll give one final warning about this being an unsupported process. But it has worked for me in my development and test environments.

Update History

  • 2022-02-15 Initial post
  • 2022-03-08 Added alternative technique

This post was last updated on June 28th, 2022 at 04:25 pm

Leave a Reply

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