IBM-MQ: Configuring mutual TLS authentication between client and queue manager

I’m trying to set up TLS mutual authentication between client and IBM-MQ queue manager (using the ibmcom/mq Docker image). The certificates are self-signed and created according to this article. As stated in the docs, it should be possible to bake in the server’s private key and both certificates into the image. My Dockerfile looks like this:

FROM ibmcom/mq

USER mqm
COPY --chown=mqm:mqm 20-config.mqsc /etc/mqm/ # creation of additional queues, no problems here
COPY --chown=mqm:mqm keys_mq1/key.key /etc/mqm/pki/keys/mykey/
COPY --chown=mqm:mqm keys_mq1/key.crt /etc/mqm/pki/keys/mykey/
COPY --chown=mqm:mqm keys_client/client.crt /etc/mqm/pki/trust/0/

The files can be found in the running container:

drwxr-xr-x 1 mqm mqm 4096 Feb 16 11:18 .
drwxr-xr-x 1 mqm mqm 4096 Feb 16 11:18 ..
-rwxr-xr-x 1 mqm mqm 1253 Feb 16 10:54 key.crt
-rwxr-xr-x 1 mqm mqm 1704 Feb 16 10:53 key.key

drwxr-xr-x 2 mqm mqm 4096 Feb 16 13:34 .
drwxr-xr-x 3 mqm mqm 4096 Feb 16 13:34 ..
-rwxr-xr-x 1 mqm mqm 1054 Feb 16 13:29 client.crt

One thing to notice is that, according to the docs, the channel details should now show the following entry: CERTLABL(mykey). In my case, it’s just CERTLABL( ). However, I’m not sure if that’s the problem here, authentication of the server without client authentication seems to be working (see below).

AMQ8414I: Display Channel details.
   ALTDATE(2020-02-16)                     ALTTIME(13.34.47)
   CERTLABL( )                             COMPHDR(NONE)
   COMPMSG(NONE)                           DESCR( )
   DISCINT(0)                              HBINT(300)
   KAINT(AUTO)                             MAXINST(999999999)
   MAXINSTC(999999999)                     MAXMSGL(4194304)
   MCAUSER(app)                            MONCHL(QMGR)
   RCVDATA( )                              RCVEXIT( )
   SCYDATA( )                              SCYEXIT( )
   SENDDATA( )                             SENDEXIT( )
   SHARECNV(10)                            SSLCAUTH(OPTIONAL)
   SSLCIPH(ANY_TLS12)                      SSLPEER( )

On client side, I created two Java keystores (JKS), one with the server’s certificate (truststore) and one with the client’s keypair.

My connection attempts were as followed:

  1. Connecting to the default queue manager QM1 using the provided app user (no password) and DEV.APP.SVRCONN channel. The client application is an existing tool that perfectly works with the existing MQ infrastructure, I just exchanged the keystores and connection details.

Client exception: JMSCMQ0001: WebSphere MQ call failed with compcode '2' ('MQCC_FAILED') reason '2035' ('MQRC_NOT_AUTHORIZED').

MQ log:

AMQ5534E: User ID 'app' authentication failed
AMQ5542I: The failed authentication check was caused by the queue manager CONNAUTH CHCKCLNT(REQDADM) configuration.
  1. Connecting using the provided admin user and DEV.ADMIN.SVRCONN channel via IBM MQ Explorer (in this scenario, I switched to admin because app has insufficient rights to be used with MQ Explorer, regardless of the authentication method). I checked the “no password” option, since I want to authenticate with the client’s certificate.

MQ Explorer error message:

Access not permitted. You are not authorized to perform this operation. (AMQ4036)
  Explanation: The queue manager security mechanism has indicated that the userid associated with this request is not authorized to access the object.

MQ log:

AMQ5540E: Application 'MQ Explorer 8.0.0' did not supply a user ID and password
AMQ5541I: The failed authentication check was caused by the queue manager CONNAUTH CHCKCLNT(REQDADM) configuration.
AMQ9557E: Queue Manager User ID initialization failed for 'admin'.
  1. Same as 2., but omitting the client’s keystore and providing the password instead. Works. The idea here was to verify that at least the server’s certificate is configured correctly (on the other hand, I’m not sure if MQ Explorer is enforcing the check of the server’s certificate against the truststore in the first place).

What am I missing?

edit: my actual goal is to use mutual authentication for the app user and DEV.APP.SVRCONN channel.

Source: StackOverflow