Creating the simplest AMS on z/OS configuration.

I was recently asked, what is the simplest configuration of certificates on z/OS to get MQ AMS working. This took me a little while to get working, so I thought it was worth documenting. To understand how to configure AMS you need to have a superficial view of what happens under the covers.

As part of writing this up I wrote

The short answer

You can have all userid use the same certificate. People in one department could all use the same certificate, which make implementing AMS much easier. You only need one recipient certificate for the team, and not have to manage people joining and leaving the team – which causes a head ache on the systems that send your system messages.

For each user

  • 1 Create a keyring for each user
  • 2 Create the CA certificate
  • 3 Create a signed user certificate with RSA, and keyusage to include DATAENCRYPT.
  • 4 , 5 Connect this certificate to all users. Make it the default certificate
  • 4 ,5 Connect this certificate to all users Connect the CA for this certificate to each user’s keyring.
  • 6 Give each userid UPDATE access to their keyring.

For the queue manager

  • 1 Create a keyring for the AMS started task userid.
  • 2 Connect to the keyring, the certificates of all recipients on this queue manager
  • 3 Connect to the keyring, all CA certificates for userids on the system, and the CAs for user on other platforms.

Refresh the AMS system. f xxxxamsm,refresh.

Simple!

The longer answer – with explanations

With AMS, you can have

  • Message integrity. The message is visible in clear text, but you can be confident it has not changed since it was created
  • Message privacy. The message is encrypted. The message can only be read by people who have access to the private key of one of the specified recipients
  • Privacy and integrity.

Background

Public and private keys

With modern ciphers, you need a pair of keys. If you encrypt with one key you need its partner to decrypt. You pick one key, and make it available to every one, and this is called the public key. You keep the other one very secure, this is called the private key.

  • If you encipher something with the public key – then only someone with the private key can decrypt it
  • If I encrypt something with my private key. Anyone can decrypt it using my public key (you may ask why bother?), but the important bit is that because you had to use my public key – you know the message came from me! We have authentication.

A certificate has a public key in it.

Quick discussion on certificate authorities

You can have self signed certificates. You should not use them, because someone could change or replace it and you would never know.

You can have signed certificates. When you create a signed certificate it creates a checksum of the certificate, and encrypt this checksum with the Certificate Authority’s private key. This encrypted checksum becomes part of the certificate.

When you receive a signed certificate you do the same checksum (and store it temporarily) then you decrypt the encrypted checksum using the CA’s public key – and the two values should match. (This assumes you have the CA certificate.)

Your Certificate Authority certificate could have been created by someone else (The UK Certificate Authority ?), and goes through the same signing process.

The UK’s Certificate Authority certificate could have been signed by someone else… so we have a chain of Certificate Authorities.

The top level in the chain of CAs is self signed.

The players

There is the putter, the getter, and the queue manager. They each need their own key ring.

Message integrity

The message is visible in clear text, but you can be confident it has not changed since it was created.

Put the message

As part of the integrity function, it calculates a checksum of the contents of the message, and encrypts this with the user’s private key. What gets sent is

  • The original payload
  • The encrypted checksum
  • The putter’s certificate
  • The putter’s CA certificate.

The putter sets up a certificate called UserCert, signed by MyCA. This certificate has certain requirements – such as it must allow data encryption, and contain an RSA public key.

The putter’s keyring needs

  • the UserCert

This needs to be the default certificate.

If the certificate belongs to the putter’s userid, then it needs read access to the keyring

PERMIT  putter.drq.ams.keyring.LST class(RDATALIB) - 
ACCESS(READ) ID(putter)

If the certificate does not belongs to the putter’s userid, then it needs update access

PERMIT   putter.drq.ams.keyring.LST class(RDATALIB) - 
ACCESS(UPDATE) ID(putter)

The UPDATE access says it can read the private key of a certificate which the userid does not own, READ access only gives you access to the public key.

For testing – give every userid UPDATE access to the keyring profile.

Get the message

When the message is got, the queue manager checks the certificate (+CA) in the message is valid, using the CA in the queue manager’s keyring. Then does the same logic as for signing a certificate.

  • Check the certificate in the message is valid (for example compare the CAs)
  • Use the public key from the certificate in the message to decrypt the checksum of the message
  • Do the same checksum calculation.
  • Compare the two answers. They should match if the message has not been tampered with.

The putter needs

  • the MyCA certificate.

The keyring is the same as for integrity.

The queue manager needs

The queue manager’s keyring needs the CA of the certificate in the message – so it can compare the it with the one in the message.

The queue manager’s userid needs only read access to its keyring. (Because it does not need access to any private keys.)

The getter needs

  • an empty keyring. (In practice AMS complains if the userid has an empty keyring because it fails to find the default certificate, so give it a certificate and make it the default).

Message privacy

The message is encrypted. The message can only be read by people who have access to the private key of one of the specified recipients

With message privacy the following happens when the message is put

  • An encryption key is generated using parameters from the putters certificate and the AMS configuration
  • The message is encrypted with this encryption key
  • From the MQ AMS definitions, there is a list of recipient’s Distinguished Names, such as CN=USER1,O=MEGACORP, and CN=USER2,OU=TEST,O=MEGACORP.
  • For each DN in the list, look in the queue manager’s keyring for the certificate with the distinguished name.
    • With the found certificate, use its public key to encrypt the encryption key
    • Build a list of [Distinguished_Name:encrypted encryption key, ….]
  • Send this list as part of the payload.

When the message is got, the getter

  • Extracts the getter’s DN from the getter’s default certificate
  • Scans the AMS data in the message for the list of [Distinguished_Name:encryption key, ….] for the matching DN
  • Uses the private key in the default certificate to decrypt the [Distinguished_Name:encryption key, ….], to get the message decryption key.
  • Use the message decryption key to decrypt the user’s message.

AMS setup

I am using a queue called AMS for my AMS testing. The AMS definitions were

setmqspl -m MQPA -p AMS -e AES128 
-r "CN=COLIN,O=AMS,C=TEST"
-r "CN=START1,O=AMS,C=TEST"
dspmqspl -m MQPA

Putter keyring

As with integrity, the putter needs access to the private key.

RACDCERT ID(COLIN )  CONNECT(RING(drq.ams.keyring )  - 
ID(COLIN ) -
default -
LABEL('AMS') )

To make the configuration easier (this is the simplest configuration, after all), the user certificate owned by ID(COLIN), and called LABEL(‘AMS’) is used by the getter userid below.

Queue manager keyring

The queue manager needs all CA certificates, and all the recipients certificates. When a recipient is specified, the queue manager’s keyring is searched for the certificate with the matching Distinguished Name. When it is found its public key is used. The private key is not used. The queue manager only requires READ access to the keyring, because it is not accessing private keys.

RACDCERT ID(STCMQ )  CONNECT(RING(drq.ams.keyring )  - 
ID(COLIN ) -
LABEL('AMS') )
RACDCERT ID(STCMQ ) CONNECT(RING(drq.ams.keyring ) -
CERTAUTH -
LABEL('NEW-CA') )
RACDCERT ID(STCMQ ) CONNECT(RING(drq.ams.keyring ) -
ID(START1) -
LABEL('AMS2') )

The getter’s keyring

RACDCERT ID(IBMUSER) CONNECT(RING(drq.ams.keyring )  - 
ID(COLIN ) -
default -
LABEL('AMS') )

RACDCERT ID(IBMUSER) CONNECT(RING(drq.ams.keyring ) -
CERTAUTH -
LABEL('NEW-CA') )

In this, the simplex configuration, the user cert is the one owned, and used by the putter. ID(COLIN) label (‘AMS’).

My definitions

Define the certificates

Define the Certificate Authority

This creates the CA called NEW-CA

//IBMRACF  JOB 1,MSGCLASS=H 
//S1 EXEC PGM=IKJEFT01,REGION=0M
//SYSPRINT DD SYSOUT=*
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD *

RACDCERT CERTAUTH DELETE(LABEL('NEW-CA'))

RACDCERT GENCERT -
CERTAUTH -
SUBJECTSDN(CN('NEW-CA')-
O('COLIN') -
OU('TEST')) -
NOTAFTER( DATE(2030-07-02 ))-
KEYUSAGE( CERTSIGN ) -
SIZE(2048) -
WITHLABEL('NEW-CA')

RACDCERT CERTAUTH ALTER (LABEL('NEW_CA')) TRUST

SETROPTS RACLIST(DIGTCERT,DIGTRING ) refresh
/*

Define the user certificate

The definition below creates the certificate for ID(COLIN) with name LABEL(AMS) and Distinguished Name CN(‘COLIN’) O(‘AMS’) C(‘TEST’).

//IBMRING  JOB 1,MSGCLASS=H 
//* https://www.ibm.com/docs/en/ibm-mq/9.4.x?topic=
//* zos-connecting-certificates-key-rings-ams
//S1 EXEC PGM=IKJEFT01,REGION=0M
//SYSPRINT DD SYSOUT=*
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD *
RACDCERT DELETE ( LABEL('AMS')) ID(COLIN)
RACDCERT ID(COLIN ) GENCERT -
SUBJECTSDN(CN('COLIN') O('AMS') C('TEST')) -
WITHLABEL('AMS') SIGNWITH(CERTAUTH LABEL('NEW-CA')) -
NOTAFTER( DATE(2027-08-05) TIME(16:22:00) ) -
KEYUSAGE(HANDSHAKE DATAENCRYPT DOCSIGN)
RACDCERT ID(COLIN ) ALTER (LABEL('AMS')) TRUST
SETROPTS RACLIST( DIGTCERT) refresh
/*

My definitions

I used JCL to (re-)define my keyrings etc. This makes it easier to make one change, and repeat. It also means I can copy them to a different system and they still work.

JCL

//IBMDEFK1 JOB 1,MSGCLASS=H
//* https://www.ibm.com/docs/en/ibm-mq/9.4.x?topic=
//* zos-connecting-certificates-key-rings-ams
//S1 EXEC PGM=IKJEFT01,REGION=0M
//SYSPRINT DD SYSOUT=*
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD *

List the certificates I use


RACDCERT LIST (LABEL('AMS')) ID(COLIN)
RACDCERT LIST (LABEL('AMS2')) ID(START1)
RACDCERT LIST (LABEL('NEW-CA')) CERTAUTH
RACDCERT LIST (LABEL('NEW-CA2')) CERTAUTH

Delete and define the keyrings.

RACDCERT ID(COLIN) DELRING(drq.ams.keyring)
RACDCERT ID(IBMUSER) DELRING(drq.ams.keyring)
RACDCERT ID(STCMQ) DELRING(drq.ams.keyring)

RACDCERT ID(COLIN) ADDRING(drq.ams.keyring)
RACDCERT ID(IBMUSER) ADDRING(drq.ams.keyring)
RACDCERT ID(STCMQ) ADDRING(drq.ams.keyring)

Connect the certificates for userid COLIN

RACDCERT ID(COLIN )  CONNECT(RING(drq.ams.keyring )  - 
ID(COLIN ) -
default -
LABEL('AMS') )
RACDCERT ID(COLIN ) CONNECT(RING(drq.ams.keyring ) -
CERTAUTH -
LABEL('NEW-CA') )

Connect the certificates for userid IBMUSER

RACDCERT ID(IBMUSER) CONNECT(RING(drq.ams.keyring )  - 
ID(START1) -
default -
LABEL('AMS') )
RACDCERT ID(IBMUSER) CONNECT(RING(drq.ams.keyring ) -
CERTAUTH -
LABEL('NEW-CA') )

Connect the certificates for the queue manager.

This has

  • All the certificates for users specified in encrypted messages with the -r…. definitons
  • All the certificate authorities used by any certificates
RACDCERT ID(STCMQ )  CONNECT(RING(drq.ams.keyring )  - 
ID(COLIN ) -
default -
LABEL('AMS') )
RACDCERT ID(STCMQ ) CONNECT(RING(drq.ams.keyring ) -
ID(COLIN ) -
default -
LABEL('AMS2') )

RACDCERT ID(STCMQ ) CONNECT(RING(drq.ams.keyring ) -
CERTAUTH -
LABEL('NEW-CA') )
RACDCERT ID(STCMQ ) CONNECT(RING(drq.ams.keyring ) -
CERTAUTH -
LABEL('NEW-CA2') )

Make these changes visible

SETROPTS RACLIST(DIGTCERT,DIGTRING ) refresh 

Give the userids access to the keyrings, and make the changes visible

PERMIT  COLIN.drq.ams.keyring.LST class(RDATALIB)   - 
ACCESS(UPDATE) ID(COLIN)
PERMIT IBMUSER.drq.ams.keyring.LST class(RDATALIB) -
ACCESS(UPDATE) ID(IBMUSER)
PERMIT STCMQ.drq.ams.keyring.LST class(RDATALIB) -
ACCESS(READ) ID(STCMQ )

SETROPTS RACLIST(RDATALIB) refresh

and display the keyrings

RACDCERT LISTRING (     drq.ams.keyring )  id(COLIN) 
RACDCERT LISTRING ( drq.ams.keyring ) id(STCMQ)
RACDCERT LISTRING ( drq.ams.keyring ) id(IBMUSER)
/*
//

Leave a Reply