The MQ documentation usually shows a local application doing a put and get, to show “how simple” it is.
Most people have a more complex environment where they have a mixture of z/OS and midrange, and clients into both.
This blog posts shows how I got clients to work with AMS on z/OS. My starting point was a working z/OS queue manager with working Java client able to put and get messages from a queue. I then enabled AMS on the z/OS queue manager.
Getting the z/OS end working
The userids on z/OS used a CA signed certificate (which is more typical in production than a self signed certificate).
Set up the xxxxAMSM keystore
My AMSM adress space has a started task userid of START1.
The xxxxAMSM address space needs a keystore, and the CA for the certificates on z/OS
#RACDCERT ID(START1) DELRING(drq.ams.keyring)
RACDCERT ID(START1) ADDRING(drq.ams.keyring)
RACDCERT ID(START1) CONNECT(CERTAUTH LABEL(‘TEMP-CA’) –
RING(drq.ams.keyring))
RACDCERT LISTRING(drq.ams.keyring) ID(START1)
Set up the keyring and certificate for the tso userid
Userid COLIN needs a keyring and an RSA certificate to identify COLIN. It is signed by “TEMP-CA”.
#RACDCERT ID(COLIN) DELRING(drq.ams.keyring)
RACDCERT ID(COLIN) ADDRING(drq.ams.keyring)
#RACDCERT ID(COLIN) DELETE(LABEL(‘AMS’))
#It defaults to certificate type RSA
RACDCERT ID(COLIN) GENCERT –
SUBJECTSDN(CN(‘COLIN’) O(‘SSS’)) –
SIZE(2048) –
SIGNWITH (CERTAUTH LABEL(‘TEMP-CA’)) –
WITHLABEL(‘AMS’)RACDCERT id(COLIN) ALTER(LABEL(‘AMS’))TRUST
# add the certificate to user’s keyring
RACDCERT ID(COLIN) CONNECT(RING(drq.ams.keyring ) –
ID(COLIN) –
DEFAULT –
LABEL(‘AMS’))# Connect the user’s public certificate to the xxxxAMSM keyring
#Usage(SITE) only exposes the public certificate, the private certificate
# is not visible in the keyring
RACDCERT ID(START1) CONNECT(ID(COLIN) LABEL(‘AMS’) –
RING(drq.ams.keyring) USAGE(SITE))RACDCERT LISTRING(drq.ams.keyring) ID(COLIN)
RACDCERT ID(COLIN) LIST
# export it so we can send public key to Linux machine.
RACDCERT ID(COLIN) EXPORT(LABEL(‘AMS’))-
DSN(‘COLIN.AMS.PEM’) –
FORMAT(CERTB64) –
PASSWORD(‘password’)# give the userid access to the keyring
permit IRR.DIGTCERT.LISTRING class(facility) access(read) id(COLIN)
setropts raclist(facility) refresh
FTP the COLIN.AMS.PEM certificate to Linux as ASCII.
Make the queue AMS protected
You need to use setmqspl to define the level of protection
// EXPORT SYMLIST=* // SET QM=CSQ9 //CSQ40CFG EXEC PGM=CSQ0UTIL, // PARM='ENVAR("_CEE_ENVFILE_S=DD:ENVARS") /' //STEPLIB DD DSN=COLIN.MQ921.SCSQANLE,DISP=SHR // DD DSN=COLIN.MQ921.SCSQAUTH,DISP=SHR //ENVARS DD DSN=COLIN.MQ921.SCSQPROC(CSQ40ENV),DISP=SHR //EXPORT DD SYSOUT=* //SYSPRINT DD SYSOUT=* //SYSIN DD *,,SYMBOLS=(JCLONLY) setmqspl -m &QM. -p AMSQ -remove setmqspl -m &QM. -p AMSQ -s SHA256 -e AES256 -a CN=COLIN,O=SSS -a "CN=testuser, O=aaaa, C=GB" -r "CN=testuser, O=aaaa, C=GB" -r CN=COLIN,O=SSS dspmqspl -m &QM. dspmqspl -m &QM. -export
Tell the xxxxAMSM address space to pick up the changes
You can use refresh all | refresh policy to get the the xxxxAMSM address space to use the changed policy information.
F xxxxAMSM,REFRESH ALL
or
F xxxxAMSM,REFRESH POLICY
Set up Linux
Create the keystore.conf
By default the configuration file used by AMS is in $HOME/.mqs/keystore.conf . I used different files, so I could test different scenarios with just one userid. I could set up a files called Alice.conf and Bob.conf so my ID can have different roles.
The location of the keystore.conf is available using
- export MQS_KEYSTORE_CONF=/home/colinpaice/mqamsclient/ks.conf for C program and
- -DMQS_KEYSTORE_CONF=/home/colinpaice/mqamsclient/ks.conf for java programs
Create a file for the configuration (/home/colinpaice/mqamsclient/ks.conf)
JKS.keystore = /home/colinpaice/ssl/ssl2/trust.jks
JKS.certificate =testuserJKS.encrypted = no
JKS.keystore_pass = zpassword
JKS.key_pass = zpassword# in V9 JKS.provider is ignored
# JKS.provider = IBMJCE
The options are documented here.
The key_pass is to access the private key within the keystore, see -keypass here. Because you are storing the clear text password in the file, it is recommended to use runamscred to encrypt the passwords.
Create the Linux keystore and certificate
I have scripts which generate my certificates, so I modified an existing one. I created a certificate with CN=testuser,O=aaaa,C=GB.
name=”testuser”
rm $name.pem $name.key.pem $key.csr $key.p12# create an RSA private key
openssl genpkey -out $name.key.pem -algorithm RSA -pkeyopt rsa_keygen_bits:2048# Create a certificate requests – so we can get it signed
openssl req -config eccert.config -passin password -sha384 -new -key $name.key.pem -out $name.csr -outform PEM -subj “/C=GB/O=aaaa/CN=”$name -passin file:password.file -passout file:password.file#use this CA
ca=”carsa1024″# sign it
openssl ca -config openssl-ca-user.cnf -policy signing_policy $ext -md sha256 -cert $ca.pem -keyfile $ca.key.pem -out $name.pem -in $name.csr $enddate -extensions clientServer#Create the .p12 file so we can import it into the .jks
openssl pkcs12 -export -inkey $name.key.pem -in $name.pem -out $name.p12 -CAfile $ca.pem -chain -name $name -passout file:password.file -passin file:password.file# remove the old one and import it
/opt/mqm/bin/runmqckm -cert -delete -db trust.jks -type jks -label $name -pw zpassword/opt/mqm/bin/runmqckm -cert -import -target trust.jks -target_type jks -file $name.p12 -label $name -pw password -target_pw zpassword
#Add the z/OS user’s public key, so we can encrypt with the certificate and public key
/opt/mqm/bin/runmqckm -cert -add -db trust.jks -type jks -file zCOLIN.PEM -label zcolin -pw zpassword# extract the Linux certificate and public key, along with its CA.
runmqckm -cert -extract -db trust.jks -pw zpassword -label $name -target $name.PEM -format ascii -type jksexit
FTP the Linux public key to z/OS and add it to the keyring
The public key for testuser was extracted to testuser.PEM ( $name.PEM above). FTP this to z/OS (in ASCII). This became file COLIN.TESTUSER.PEM on z/OS.
To simplify the administration, you could setup an ID to “own” the certificates for each enterprise you work with. For example certificates from YOURORG are attached to ID(YOURORG).
I’ve used id ADCDA.
#Try to delete it if needed
#RACDCERT ID(ADCDA) DELETE (LABEL(‘LINUXTESTUSER’))
RACDCERT ADD(‘COLIN.TESTUSER.PEM’) –
ID(ADCDA) WITHLABEL(‘LINUXTESTUSER’) TRUST# Connect it to the xxxxAMSM’s keyring
RACDCERT ID(START1) CONNECT(RING(drq.ams.keyring ) –
ID(ADCDA) LABEL(‘LINUXTESTUSER’))
Tell xxxxAMAM to pick up the updated keystore
You can use refresh all | refresh keystore to refresh the xxxxAMSM keyring information
f CSQ9AMSM,REFRESH ALL
or
f CSQ9AMSM,REFRESH keyring
Run the java client
. /opt/mqm/java/bin/setjmsenv64
#Java does not used export MQS_KEYSTORE_CONF=/home/colinpaice/mqamsclient/ks.conf
ksc=”-DMQS_KEYSTORE_CONF=/home/colinpaice/mqamsclient/ks.conf”
lib=”-Djava.library.path=/opt/mqm/java/lib64″#java $lib $ksc JmsBrowser -m CSQ9 -d AMSQ -h 10.1.1.2 -p 1414 -l SYSTEM.DEF.SVRCONN
#java $lib $ksc JmsConsumer -m CSQ9 -d AMSQ -h 10.1.1.2 -p 1414 -l SYSTEM.DEF.SVRCONN
java $lib $ksc JmsProducer -m CSQ9 -d AMSQ -h 10.1.1.2 -p 1414 -l SYSTEM.DEF.SVRCONN
Any error messages are written to file mqjms.log.0 .
Other AMS blog posts
- Overview and challenges of using end to end message encryption (AMS).
- Certificate and keyring management for AMS.
- Installing AMS on z/OS.
- What certificates do I need for AMS with a client going to z/OS?
- checkAMS: program to check your AMS defintions are consistent with z/OS keyring
- Adding more users to AMS.
- Installing AMS on midrange for end to end message protection
- Understanding setmqspl to set up AMS definitions.
- How to administer AMS policies, and use the set policy command.
- Brain check and reset, needed for AMS keystores on midrange.
- Using runamscred to encrypt the passwords in the keystore.conf file.
- How do I find the recipients and signer of an AMS message?
- I have a message on the AMS DLQ – what can I do about it? and How do I process messages on the dead letter queue (DLQ)?