mqweb what’s the difference between the message API and the admin API?

At first glance it looks like the answer is in the question.  You can use

  • the messaging REST API put and get messages
  • the admin REST API to administer queue manager objects

In a couple of places the IBM documentation says you can use the messaging API to administer your objects, which is true at the general sense, but not the specific sense.  Until I hit a problem I thought there was one “messaging REST API” with different flavors of syntax.

Security

The admin API authorisation is managed through <security-role name=”MQWebAdmin”> and <security-role name=”MQWebAdminRO”> sections in the mqwebuser.xml file.

The messaging API authorisation is managed through <security-role name=”MQWebUser”> sections.

Access to resources is done using the Alternate Userid.  I can see in the activity trace that the userid is colinpaice(the id mqweb is running under), but the open of a queue was done with alternate userid testuser.  When I tried to browse messages on a queue, I got a message saying my userid did not have the correct authority. I used setmqaut, and mqsc command refresh security(*) to resolve it.

Cost of the admin interface

The admin interface has a request like

https://127.0.0.1:9443/ibmmq/rest/v1/admin/qmgr/QMA/queue/CP0000?attributes=*

which returns all of the attributes of the queue CP0000.  From the activity trace we can see

  • MQCONN + MQDISC
  • MQOPEN, MQINQ, MQCLOSE of the manager object – twice
  • MQOPEN, MQPUT, MQCLOSE to the SYSTEM.ADMIN.COMMAND.QUEUE
  • MQOPEN, MQGET, MQCLOSE to the SYSTEM.REST.REPLY.QUEUE
  • MQCMIT
  • MQBACK – the JMQI code always does this to be sure that there is no outstanding unit of work,

The most expensive request is the MQCONNect.

Using the admin interface is fine for administration because changes to objects are usually done infrequently.   If you are considering the admin interface to monitor objects, for example plot queue depths over time, the mq rest API may not be the best solution.

Cost of the messaging interface

The messaging API interface uses connection pooling.   When the application does an MQDISC, the connection is returned to a pool, and can be reused if the same userid does an MQCONN.  If the connection is not used for a period, it can be removed from the pool and an MQDISC done to release the connection.    This should eliminate frequent MQCONN and MQDISCs.

From the activity trace we see

MQOPEN, MQGET,MQGET,MQCLOSE of the queue, and no MQCONN.

There will be an MQCONN, is there is no connection available for that userid in the pool, but this should be infrequent.

Python and mq REST api

I found cURL a good way of using the mq REST API, but I wanted to do more.  cURL depends on a package called libcurl, which can be used by other languages.

Python seemed the next obvious place to look.

As I have found out, using digital certificates for authentication is hard to set up, and using signed certificates is even harder.  As I had done the hard work of setting up the certificates before I tried curl and Python, the curl and Python experience was pretty easy.

I looked at using the Python “request” package.   This allows you to specify most of the parameters that libcurl needs, except it does not allow you to specify the password for the user’s keystore.

I then looked at the Python package pycurl package.    This is a slightly lower level API, but got it working in an hour or so.
My whole program is below.

During the testing I got various errors, such as “77”.  These are documented here. 

The messages were clear, for example

CURLE_SSL_CACERT_BADFILE (77) Problem with reading the SSL CA cert (path? access rights?).

Which was enough to tell me where to look.

All the things you can do with curl, you can do with pycurl.

 

# program - based on code in http://pycurl.io/docs/latest/quickstart.html
import sys
import pycurl

from io import BytesIO

# header_function take from http://pycurl.io/docs/latest/quickstart.html
headers = {}
def header_function(header_line):
# HTTP standard specifies that headers are encoded in iso-8859-1.

header_line = header_line.decode('iso-8859-1')

# Header lines include the first status line (HTTP/1.x ...).
# We are going to ignore all lines that don't have a colon in them.
# This will botch headers that are split on multiple lines...
if ':' not in header_line:
  return

# Break the header line into header name and value.
name, value = header_line.split(':', 1)
print("header",name,value)

home = "/home/colinpaice/ssl/ssl2/"
ca=home+"cacert.pem"
cert=home+"testuser.pem"
key=home+"testuser.key.pem"
cookie=home+"cookie.jar.txt"
url="https://127.0.0.1:9443/ibmmq/rest/v1/admin/qmgr/QMA/queue/CP0000?attributes=type"
buffer = BytesIO()
c = pycurl.Curl()
print("C=",c)
try:
  # see option names here https://curl.haxx.se/libcurl/c/curl_easy_setopt.html
  # PycURL option names are derived from libcurl
  # option names by removing the CURLOPT_ prefix. 
  c.setopt(c.URL, url) 
  c.setopt(c.WRITEDATA, buffer) 
  c.setopt(pycurl.CAINFO, ca) 
  c.setopt(pycurl.CAPATH, "") 
  c.setopt(pycurl.SSLKEY, key) 
  c.setopt(pycurl.SSLCERT, cert) 
  c.setopt(pycurl.SSL_ENABLE_ALPN,1)
  c.setopt(pycurl.HTTP_VERSION,pycurl.CURL_HTTP_VERSION_2_0)
  c.setopt(pycurl.COOKIE,cookie) 
  c.setopt(pycurl.COOKIEJAR,cookie) 
  c.setopt(pycurl.SSLKEYPASSWD , "password") 
  c.setopt(c.HEADERFUNCTION, header_function)  
# c.setopt(c.VERBOSE, True)
  c.perform() 
  c.close()
except Exception as e: 
  print("exception :",e ) 
finally: 
  print("done") 
body = buffer.getvalue() # Body is a byte string. 
# We have to know the encoding in order to print it to a text file 
# such as standard output. 
print(body.decode('iso-8859-1'))

 

Getting mqweb into production

You’ve got mqweb working,  you can now do administration using the REST API, or use a web browser in your sandbox environment to manage a queue manager.  You now want to get it ready for production – so where do you start?

I’ll document some of the things you need to do.  But to set the the scene, consider your environment

  • Production and test
  • Two major applications, accounts and payroll
  • You have multiple machines for each application, providing high availability and scalability
  • Teams of people
    • The MQ administration team who can do anything
    • The MQ RO administration team who can change the test systems, but have read only access to production
    • The applications teams who can change their test environment, but only have read only access to production
  • You will use signed certificates (because this is production)  and not use passwords.
  • People will get the same dashboard,  to make training and use easier.
  • You want to be able to quickly tell if a dashboard is for production or test, and accounts and payroll
  • You want to script deployment, so you deployment to production can be done with no manual involvement.
  • You want a secure, available solution.

The areas you need to consider are

  • the mqwebuser.xml file
  • the keystore for the mqweb certificate
  • the trust store for the authorisation certificates
  • the dashboard for each user
  • each user’s certificate store with their private keys
  • Displaying the statistics on the mq console and REST requests.

Setting up security

It is better to give access using groups rather than by individual ids.

  • If some one joins or leaves a team, you have to update one group, rather than many configuration files.
    • This is easier to do, and is easier to audit
  • The control is in the right place.  For example the manager of the accounts team should mange the accounts group.  The MQ team should not be doing userid administration on the accounts group.

You will need groups for

  • MQ Systems Administrators who can administer production and test machines
  • MQ Systems  RO Administrators,  who can administer test machines, and have read access to production machines.
  • Payroll – the applications manager may want more granular groups.
  • Accounts  – the applications manager may want more granular groups.

You will need to set up the groups on each machine (you may well have this already).

Queue security

REST users need get and put access to SYSTEM.REST.REPLY.QUEUE.

For example

setmqaut -m QMA -n SYSTEM.REST.REPLY.QUEUE -t q -g test +get +put

then runmqsc refresh security

Set up the mqwebuser.xml file

The same file can be used for the different machines for “Accounts – production”, and a similar file for “Accounts – test” etc.

You may want to use “include”  files, so have one file imbedded in more than one mqwebuser.xml file.

Do not use the setmqweb command.   This will update the copy on the machine, and it will be out of sync with the master copy in your repository.

Define roles

The production environment for payroll may have

 <security-role name="MQWebAdmin">
   <group name="MQSA"/>
</security-role>

<security-role name="MQWebAdminRO">
  <group name="MQSARO"/>
  <group name="PAYROLL"/>
</security-role>

The test environment for payroll may have

<security-role name="MQWebAdmin">
   <group name="MQSA"/>
   <group name="MQSARO"/>
   <group name="PAYROLL"/>
</security-role>

<security-role name="MQWebAdminRO">
  <!-- none -all admin users can change test-->
</security-role>

Define http settings

By default mqweb is set up for localhost only.  You will need to have

  • <variable name=”httpHost” value=”hostname” />

where hostname specifies the IP address, domain name server (DNS) host name with domain name suffix, or the DNS host name of the server where IBM MQ is installed. Use an asterisk, *, to specify all available network interfaces.

You may need to change the port value from

  • <variable name=”httpsPort” value=”9443″/>

Define the keystore in mqwebuser.xml

Decide on the names and location of the key stores

  • <keyStore id=”defaultKeyStore” location=”/home/mq/payrollproductionkeystore.p12” type=”pkcs12″ password=”{aes}AMsUYgpOjy+rxR7f/7wnAfw1gZNBdpx8RpxfwjeIG8Wj”/>
  • <keyStore id=”defaultTrustStore” location=”/home/mq/payrollproductiontruststore.jks” type=”JKS” password=”{aes}AJOmiC8YKMFZwHlfJrI2//f2Keb/nGc7E7/ojSj37I/5″/>

Encrypt the keystore passwords  using the /opt/mqm/web/bin/securityUtility command. See here.

Ensure the deployment process gives the files the appropriate access.  The key store includes the private key, so needs to be protected.  The trust store should only have information in the “public” domain, such as certificates and no private keys, so could be universally read.

Set up the keystores

The keystore has the certificate and private key which identifies the server.  The certificate needs the subjectAltName specified which has a list of valid url names and IP addresses.
You need to decide if you want one certificate per server, and so have several certificates

subjectAltName = DNS:payroll1, IP:10.4.6.1

or several systems in the list, and have one certificate

subjectAltName = DNS:payroll1, DNS:payroll2, IP:10.4.6.1,  IP:10.9.5.4

You may want to create the keystore on your build environment, and securely deploy it to the run time machines, or send the .p12 file across and import it.  I think creating the keystore and deploying it is more secure.

If you change the keystore you have to restart mqweb to pickup changes.

Set up the trust store.

The trust store is used to validate certificates sent from the client for authentication.  In an ideal work, this will have just one CA certificate.  You may have more than one CA.  If you have self signed certificates this creates a management problem.

You may be able to use the same trust store for all your environments.   The access control is done by the security-roles in the mqwebuser.xml, not by the trust store.

The cn from the certificate is used as the userid. So both

cn=colinpaice,ou=test,o=sss and cn=colinpaice,ou=prod,o=sss are valid, and would extract userid colinpaice.

If the trust store is changed, the mqweb server needs to be restarted.

End user certificates

Each user will need a certificate to be able to access the mqweb server.  This needs to be signed by your CA, and needs to be set to trusted.  You should have this set up already.

If you have more than one valid certificate in the browser store, you will be prompted to pick one.   This is used until the browser is restarted.

You can configure mqweb to log off users after a period.   If you are using certificates, the browser will automatically log you on again!

Dashboard

The dashboard is the layout of the mqweb window, the tabs in the window, and the widgets on the tabs.

You will generally want users to have the template you define, and not have to create their own. So the Payroll team use the payroll dashboard, and the MQ admin team use the MQADMIN dashboard.

Create a dashboard and use export to create a json file.   You can store in your configuration repository.   You can change queue manager names as you deploy it for example change QMPayroll1 to QMPayroll2.

On the MQ machines these files are stored in the  /var/mqm/web/installations/Installation1/angular.persistence directory.

You can put your templates for that machine in this directory, and use symbolic links for a userid to their dashboard. For example

ln -s common.json colinpaice.json

If the dashboard.json is made read only, then people will not be allowed to change it online.

 

Is this dashboard for production or test?

I could not find a way of customise the colours of a page, so you cannot easily tell which is production and which is test etc.

I need a secure available solution.

You can use userids and passwords, or certificates to provide authentication.

You need to protect access to MQ objects

You need to protect the files used by mqweb, especially the key store, and the mqwebuser.xml

If you update the mqwebsuser.xml file, it will pickup up changes a short while later (seconds rather than minute).

If you change the keystore or trust store you need to restart mqweb to pick up the changes.   This should take about 10s of  seconds.

Deploy scripts

All of the configuration can be done with scripts.  For example extract your mqwebuser.xml file, make machine specific changes and deploy it.

You can create the keystores in your secure build environment and deploy them.

House keeping

  • You should check /var/mqm/web/installations/Installation1/servers/mqweb/logs/ffdc daily for any files, and raise a PMR with PMR if you get any exceptions.
  • Check /var/mqm/web/installations/Installation1/servers/mqweb/ daily.  I was getting large (700MB) dumps in this directory, which caused my machine to go short on disk space.
  • Display the server certificate expiry date (any any CA certificates) and put a date in your diary to check (and renew) them.
  • Your enterprise should have a process for renewing personal certificates

Someone joins the department

  • Connect them to the appropriate group on all machines
  • Give them a symbolic link to the appropriate dashboard file, in /var/mqm/web/installations/Installation1/angular.persistence

Collect statistics on the MQ console and REST requests, and the JVM

See these posts

Using IBM api explorer to display the syntax of mq rest commands.

You can use an url like https://localhost:9443/ibm/api/explorer  to display the mqweb api documentation.  The documentation is in swagger format, available in a web browser.   This is the same information you get from a REST request see here.

If you enter the url in the web browser, and you are using certificate authentication, you will be prompted with a list of valid certificates.  Any certificate is valid.   Even one with a CN=unknown was accepted.   The information is read only so this is not an issue.

The web page has

  • API Discovery
  • channel
  • login

If you click login it gives

  • DELETE /ibmmq/rest/v1/login  
    • Logs out a user
  • GET   /ibmmq/rest/v1/login
    • Queries the authenticated user and their roles.
  • POST  /ibmmq/rest/v1/login
    • Logs out a user

If you click on an item it displays more information, in a nice, easy to read format.  Much easier to read than if you retrieved it using the REST API.

What it doesn’t tell you

It does not tell you to put ?attributes=*&status=* on the end of your query to get queue attributes, and qstatus returned, as in https://127.0.0.1:9443/ibmmq/rest/v1/admin/qmgr/QMA/queue/CP0000?attributes=*&status=*See here for more information.

Using the url as a REST request.

Using the url from curl and –user colinpaice:password gave

curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to localhost:9443

Using certificate authentication nothing was returned.

Using certificate authentication and the –include option (include headers)

url –include https://localhost:9443/ibm/api/explorer –cacert cacert.pem –cert colinpaice.pem:password –key colinpaice.key.pem

gave

HTTP/1.1 401 Unauthorized

So using the explorer url is not allowed.

mqweb – how to use the REST api commands.

You can issue MQ commands using the REST API vai the mqweb server, for example with python or curl.  The problem I had was trying to remember the syntax of the commands.  You can access this information from your program by using the “swagger” interface.  You can can access it from a browser (easiest), or from a REST request (for the experts).

I found it useful to use a curl query logon request to check the validity of the certificates I was using.  I could use the –trace curl.trace.txt to capture the data flows.  If this worked, problems were likely to be in the browser set up, rather than the certificate set up.

Note: Swagger is the name of a protocol, not an acronym.

You need to configure mqweb to use Swagger.

<featureManager>
  <feature>apiDiscovery-1.0</feature>
</featureManager>

Then use a request like (for certificate authentication)

curl -i https://localhost:9443/ibm/api/docs –cacert cacert.pem –cert colinpaice.pem:password –key colinpaice.key.pem > swagger.out

where (note the ‘–‘ may be double – – )

  • curl – issue the command
  • -i  – include the http headers in the response.  This is the same flag as –include
  • https://localhost:9443/ibm/api/docs – this url
  • –cacert cacert.pem – use this CA certificate
  • –cert colinpaice.pem:password – use this user certificate
  • –key colinpaice.key.pem – use this user private key
  • > swagger.out – write the output to this file

If you are using self signed you should use the –insecure option otherwise you get

curl: (60) SSL certificate problem: self signed certificate in certificate chain
More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

If you try to userid and password you get

curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to localhost:9443

The swagger output

The output contains

{
  "swagger" : "2.0",
  "info" : {
    "description" : "Discover REST APIs available within Liberty",
    "version" : "1.0.0",
    "title" : "Liberty REST APIs"
},
  "host" : "localhost:9443",
  "tags" : [ {
    ...
    "name" : "qmgr"
    ...
    "name" : "login"
    ...
    "name" : "API Discovery",
    "description" : "APIs available from the API Discovery feature"
} ],
...

We can see there is a login command.  You have to search the json for the data with “tags”  : [“login”].

The section for login has

"/ibmmq/rest/v1/login" : {
  "get" : {
    "tags" : [ "login" ],
    "summary" : "Queries the authenticated user and their roles.",
    "description" : "Retrieves details of the authenticated user and their roles.",
    "operationId" : "getLogin",
    "produces" : [ "application/json; charset=utf-8" ], 
    "parameters" : [ ],
    "responses" : {
      "200" : {
         "description" : "A JSONArray that contains JSONObjects that describe the authenticated user.",
         "schema" : {
            "$ref" : "#/definitions/UserAttributePojo"
              }
     },
...

“get”

Within the partial url /ibmmq/rest/v1/login are sections “get”, “post”, and “delete”:

  • “get” –   Queries the authenticated user and their roles  – as the “summary” tag says
  • “post”  – Authenticates a user and returns an authentication token.
  • “delete” – Deletes the authentication token of the logged in user.

You need to pick the section for what you want to do within “get”, “post”, “delete”

“tags” : [ “login” ]

This is for the request.

“200”

This is one of the list of return codes from the http request, and the data each returns.

This returns data as defined in the schema, “$ref” : “#/definitions/UserAttributePojo” .  Look in the rest of the document for this section called definitions, with UserAttributePojo underneath.

“definitions”: UserAttributePojo

 "definitions" : {

...
 "UserAttributePojo" : {
    "type" : "object",
    "required" : [ "name", "role" ],
    "properties" : {
      "name" : {
      "type" : "string"
      },
     "role" : {
       "type" : "array",
        "items" : {
          "type" : "string"
         }
      }
  }

Two strings will be returned, name and role.

Issue the command

From the data in the swagger output,  we can see  “host” : “localhost:9443” and “/ibmmq/rest/v1/login” : { “get” : {

build the command

https://localhost:9443/ibmmq/rest/v1/login –request get

my command is now

curl -i https://localhost:9443/ibmmq/rest/v1/login –cacert cacert.pem –cert colinpaice.pem:password –key colinpaice.key.pem –trace trace.txt –request get

note: -request get is inferred and can be allowed to default.

and it returns

{"user": [{
  "name": "colinpaice",
  "role": [
    "MQWebAdmin",
    "MQWebAdminRO",
    "MQWebUser"
  ]
}]}

If you want to pass data with quotes in it – for example json data. Create a file, and use that
for example
curl -i …  –request post -H “Content-Type: application/json” -d @curl.json.txt 

or use

-d "{\"param\":\"value\"}"

which is not so easy.

Setting up the end user self signed certificate for mqweb

This post describes how to set up self signed certificates to authenticate end user’s access to mqweb.

You can use self signed, which is fine for test and small environments, or use signed certificate which are suitable for production,  and typical environments.  Using certificates means you do not need to specify userid and password.

The userid is taken from the CN part of the subject, and this userid is used to grant access depending on the configuration in the mqwebuser.xml file.

Information about certificates used for authentication are stored in the trust store.  For a CA signed certificate, you only need the CA certificates, not the individual certificates.  With self signed, you need a copy of the individual self signed certificate in the mqweb trust store.

Create the trust store if required.

/opt/mqm/bin/runmqckm -keydb -create -db trust.jks -pw zpassword -type jks

You need to do this once.

Create the self signed certificate for the end user

openssl req -x509 -config openssl-client2.cnf -newkey rsa:2048 -out testuser.pem -keyout testuser.key.pem -subj “/C=GB/O=aaaa/CN=testuser” -extensions ss_extensions -passin file:password.file -passout file:password.file

  • openssl req -x509  –x509 makes this a self signed request
  • -config openssl-client2.cnf – use this config file
  • -newkey rsa:2048 – create a new private key with 2048 bits rsa key
  • -out testuser.pem – put the request in this file
  • -outform PEM – with this format
  • -keyout testuser.key.pem – put the key in this file
  • -subj “/C=GB/O=aaaa/CN=testuser” – this is the DN.   The CN= is the userid used by mqweb to determine the role.  It must match the case of userid
  • -extensions ss_extensions – see below
  • -passin file:password.file -passout file:password.file – passwords are in this file
[  ss_extensions  ]

subjectKeyIdentifier = hash
#Note: there is a bug in Chrome where it does 
# not accept certificates if basicConstraints
# is specified
# basicConstraints   = CA:false
subjectAltName       = DNS:localhost, IP:127.0.0.1
nsComment            = "OpenSSL Self signed Client"
keyUsage             = critical, keyEncipherment
extendedKeyUsage     = critical, clientAuth

Create an intermediate pkcs12 keystore so it can be imported to your browser.

You need to import the certificate and private key into the browser’s keystore.   The only way I found of doing this was via an intermediate pkcs12 keystore (with extension .p12).   If you import the certificate and key from the web browser, it will expect a .p12 file.

openssl pkcs12 -export -in testuser.pem -inkey testuser.key.pem -out testuser.p12 -name “testuser” -passin file:password.file -passout file:password.file

  • openssl pkcs12 – request to process a pkcs12 keystore
  • -export – to create it
  • -inkey testuser.key.pem – this private key
  • -in testuser.pem – this certificate returned from the CA
  • -out ssks.p12 – the name of the key store which is created
  • -name testuser – create this name in the keystore
  • -passout file:password.file -passin file:password.file – use these passwords

Import the intermediate keystore into the trust store

/opt/mqm/bin/runmqckm -cert -import -target trust.jks -target_type jks -file testuser.p12 -label testuser -pw password -target_pw zpassword

  • /opt/mqm/bin/runmqckm – run this command
  • -cert – we want to process a certificate
  • -import – w want to import a file
  • -target trust.jks – this is the mqweb trust store
  • -target_type jks – it is a jks store
  • -file testuser.p12 – input file
  • -label testuser – this is the label in the trust.jks keystore
  • -pw password – the password of the testuser.p12
  • -target_pw zpassword – the password of the trust.jks keystore

In the message.log I had

E CWPKI0022E: SSL HANDSHAKE FAILURE: A signer with SubjectDN CN=testuser, O=aaaa, C=GB was sent from the target host. The signer might need to be added to local trust store /home/colinpaice/ssl/ssl2/trust.jks, located in SSL configuration alias defaultSSLConfig. The extended error message from the SSL handshake exception is: PKIX path validation failed: java.security.cert.CertPathValidatorException: The certificate issued by CN=testuser, O=aaaa, C=GB is not trusted; internal cause is:
java.security.cert.CertPathValidatorException: Certificate chaining error

When I restarted mqweb and the certificate was accepted.

I had the same message when I did not import the certificate into the trust store.

Import the temporary keystore into the Chrome keystore

pk12util -i testuser.p12 -d sql:/home/colinpaice/snap/chromium/986/.pki/nssdb/ -W password

  • pk12util   – this command
  • -i  testuser.p12  – from this keystore
  • -d sql:/home/colinpaice/snap/chromium/971/.pki/nssdb/ – into this key store
  • -W password  – using this password (for the temporary .p12 file)

Remove the intermediate file

rm testuser.p12

Update the mqweb configuration

<webAppSecurity allowFailOverToBasicAuth="false" />
<keyStore id="defaultKeyStore" 
          location="/home/colinpaice/ssl/ssl2/mqweb.p12" 
          type="pkcs12" 
          password="password"/>

<keyStore id="defaultTrustStore" 
          location="/home/colinpaice/ssl/ssl2/trust.jks" 
          type="JKS" 
          password="password"/>

<ssl     id="defaultSSLConfig" 
         keyStoreRef="defaultKeyStore" serverKeyAlias="mqweb" 
         trustStoreRef="defaultTrustStore" sslProtocol="TLSv1.2"
         clientAuthentication="true" 
         clientAuthenticationSupported="true" 
/>

Stop mqweb

You need to restart mqweb so it picks up any changes to the trust store.

/opt/mqm/bin/endmqweb

Start mqweb

/opt/mqm/bin/strmqweb

No messages are produced in  /var/mqm/web/installations/Installation1/servers/mqweb/logs/messages.log if the trust store was opened successfully.

Use a command like grep ” E ” messages.log  and check for messages like

CWPKI0033E: The keystore located at /home/colinpaice/ssl/ssl2/trust.jks did not load because of the following error: Keystore was tampered with, or password was incorrect

Try using it in Chrome

You need to restart Chrome to pick up the changes to its keystore.  Use the url chrome://restart/

Use the url chrome://settings/certificates , to check your certificate is present under “Your certificates”. If not use url chrome://version to display the profile being used, and that it matches the store used in the pk12util command above.

Try connecting to mqweb using a url like https://127.0.0.1:9443/ibmmq/console/ .

You should be logged on with no password request. In the top right hand corner of the screen you should have a black circle with a white “i” in it.   This shows you are logged on with certificates.

Setting up the end user CA signed certificate for mqweb

You want to use certificates to authenticate access to a mqweb server.  You can use self signed, which is fine for test and small environments, or use signed certificate which are suitable for production,  and typical environments.  Using certificates means you do not need to specify userid and password.

The userid is taken from the CN part of the subject, and this userid is used to grant access depending on the configuration in the mqwebuser.xml file.

This section assumes you have set up your mqweb using a certificate authority.

Information about certificates used for authentication are stored in the trust store.  For a CA signed certificate, you only need the CA certificates, not the individual certificates.  With self signed, you need a copy of the individual self signed certificate.

Create the trust store if required.

/opt/mqm/bin/runmqckm -keydb -create -db trust.jks -pw zpassword -type jks

You need to do this once.

Add the CA certificate to the trust store

/opt/mqm/bin/runmqckm -cert -add -db trust.jks -file cacert.pem -label CACert -type jks -pw zpassword

You need to do this for each CA certificate you want to add, giving each CA a unique label.

You need to restart mqweb so it picks up any changes to the trust store, but as you will be changing the mqwebuser.xml – the restart can wait will later.

Create the certificate request for the end user

openssl req -config client.cnf -newkey rsa:2048 -out colinpaice.csr -outform PEM -keyout colinpaice.key.pem -subj “/C=GB/O=cpwebuser/CN=colinpaice” -extensions client_extensions -passin file:password.file -passout file:password.file

  • openssl req – the absence of -x509 makes this a certificate request
  • -config client.cnf – use this config file
  • -newkey rsa:2048 – create a new private key with 2048 bits rsa key
  • -out colinpaice.csr – put the request in this file
  • -outform PEM – with this format
  • -keyout colinpaice.key.pem – put the key in this file
  • -subj “/C=GB/O=cpwebuser/CN=colinpaice” – this is the DN.   The CN= is the userid used by mqweb to determine the role.  It must match the case of userid
  • -extensions client_extensions – see below
  • -passin file:password.file -passout file:password.file – passwords are in this file
[ client_extensions ]

subjectKeyIdentifier = hash
# basicConstraints = CA:FALSE
subjectAltName       = DNS:localhost, IP:127.0.0.1
nsComment = "OpenSSL ColinClient"
keyUsage = critical, nonRepudiation,digitalSignature,
extendedKeyUsage = critical, clientAuth

You need to do this for each user.

Sign it

Send the certificate request to your CA.  You can use the following command to sign it.

openssl ca -config openssl-ca-user.cnf -policy signing_policy -extensions signing_req -md sha256 -keyfile cacert.key.pem -out colinpaice.pem -infiles colinpaice.csr

  • openssl ca – the signing request
  • -config openssl-ca-user.cnf – use this config file
  • -policy signing_policy – defines the requirements for the DN.  See below
  • -extensions signing_req – see below
  • -md sha256 – what encryption to be used for the message digest
  • -keyfile cacert.key.pem – the CA authorities private key
  • -out colinpaice.pem – where the output goes
  • -infiles colinpaice.csr – the input file that needs signing

Send the *.pem file back to the requestor.

You need to do this for each user.

The signing policy allows the CA administrator to define which elements are required in the DN.

[ signing_policy ]
organizationName = supplied
commonName = supplied

The certificate needs extensions which say how the certificate can be used.

[ signing_req ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
basicConstraints    = CA:FALSE
keyUsage            = digitalSignature
extendedKeyUsage    =  clientAuth

Create an intermediate pkcs12 keystore so certificate can be imported

You need to import the certificate and private key into the browser’s keystore.   The only way I found of doing this was via an intermediate pkcs12 keystore (with extension .p12).   If you import the certificate and key from the web browser, it will expect a .p12 file.

openssl pkcs12 -export -inkey colinpaice.key.pem -in colinpaice.pem -out colinpaice.p12 -CAfile cacert.pem -chain -name colinpaice -passout file:password.file -passin file:password.file

  • openssl pkcs12 – request to process a pkcs12 keystore
  • -export – to create it
  • -inkey colinpaice.key.pem – this private key
  • -in colinpaice.pem – this certificate returned from the CA
  • -out colinpaice.p12 – the name of the temporary key store which is created
  • -CAfile cacert.pem – use this CA certificate
  • -chain – include any CA certificates with the certificate and key
  • -name colinpaice – create this name in the keystore
  • -passout file:password.file -passin file:password.file – use these passwords

Import the temporary keystore into the Chrome keystore

pk12util -i colinpaice.p12 -d sql:/home/colinpaice/snap/chromium/986/.pki/nssdb/ -W password

  • pk12util   – this command
  • -i  colinpaice.p12  – from the temporary keystore you just created
  • -d sql:/home/colinpaice/snap/chromium/986/.pki/nssdb/ – into this key store
  • -W password  – using this password (for the temporary .p12 file)

Remove the intermediate file

rm colinpaice.p12

You do not need to import the certificate into the mqweb trust store.

Update the mqweb configuration if required

<webAppSecurity allowFailOverToBasicAuth="false" />
<keyStore id="defaultKeyStore" 
          location="/home/colinpaice/ssl/ssl2/mqweb.p12" 
          type="pkcs12" 
          password="password"/>

<keyStore id="defaultTrustStore" 
          location="/home/colinpaice/ssl/ssl2/trust.jks" 
          type="JKS" 
          password="password"/>

<ssl     id="defaultSSLConfig" 
         keyStoreRef="defaultKeyStore" serverKeyAlias="mqweb" 
         trustStoreRef="defaultTrustStore" sslProtocol="TLSv1.2"
         clientAuthentication="true" 
         clientAuthenticationSupported="true" 
/>

Stop mqweb

It is better to stop and restart mqweb if you change the xml config files, otherwise you can get strange errors.

/opt/mqm/bin/endmqweb

Start mqweb

/opt/mqm/bin/strmqweb

No messages are produced in  /var/mqm/web/installations/Installation1/servers/mqweb/logs/messages.log if the trust store was opened successfully.

Use a command like grep ” E ” messages.log  and check for messages like

CWPKI0033E: The keystore located at /home/colinpaice/ssl/ssl2/trust.jks did not load because of the following error: Keystore was tampered with, or password was incorrect

Try using it in Chrome

You need to restart Chrome to pick up the changes to its keystore.  Use the url chrome://restart/

Use the url chrome://settings/certificates , to check your certificate is present under “Your certificates”. If not use url chrome://version to display the profile being used, and that it matches the store used in the pk12util command above.

Try connecting to mqweb using a url like https://127.0.0.1:9443/ibmmq/console/ .

You should be logged on with no password request. In the top right hand corner of the screen you should have a black circle with a white “i” in it.   This shows you are logged on with certificates.  Click on this to show how you are logged on.

Setting up a self signed certificate for the mqweb server end

When using mqweb with certificates you can use

  • a self signed certificate to identify the server
  • a CA signed certificate to identify the server

You can use certificates to authenticate…

  • a self signed certificate at the client end
  • a CA signed certificate at the client end

This post explains how I set up mqweb to use a self  signed certificate at the server, and to import the certificate into my Chrome browser.

The tasks are

  • create the self signed certificate
  • create the keystore and import the certificate
  • update the mqwebuser.xml file
  • import the certificate into the browser keystore

Create the openssl config file

You configure parameters in sections in a config file, and use a command parameter to identify which sections to use.

For the self signed certificiate I set up ss_extensions

[ ss_extensions ]

subjectKeyIdentifier = hash
#Note: there is a bug in Chrome where it does 
# not accept certificates if basicConstraints
# is specified
# basicConstraints = CA:false

subjectAltName = DNS:localhost, IP:127.0.0.1
nsComment = "OpenSSL ColinClientSS28"
keyUsage = critical, keyEncipherment
extendedKeyUsage = critical, serverAuth

Create the self signed certificate

I set up a shell script to automate the tasks

Create the self signed certificate

openssl req -x509 -config openssl-client2.cnf -newkey rsa:2048 -out ss.pem -keyout ss.key.pem -subj “/C=GB/O=aaaa/CN=colinpaice” -extensions ss_extensions -passin file:password.file -passout file:password.file

  • -config openssl-client2.cnf  – the location of the openssl configutation file ( see -extensions)
  • -newkey rsa:2048 – define a self signed certiticate
  • -out ss.pem – where the certificate is stored
  • -keyout ss.key.pem– where the private key is stored
  • -subj “/C=GB/O=aaaa/CN=colinpaice” – this is the DN of the certificate.  I Used O=aaaa so it was at the top of any list of certificates
  • -extensions ss_extensions see above
  • -passin file:password.file -passout file:password.file – openssl uses passwords. The file has two lines each with a password in it.

delete the old keystore

rm ssks.p12

  • delete the old keystore

create the keystore and import the certificate

openssl pkcs12 -export -in ss.pem -inkey ss.key.pem -out ssks.p12 -name “server” -passin file:password.file -passout file:password.file

  • pkcs12 -export – create the pkcs12 keystore
  • -in ss.pem -inkey ss.key.pem – the two files which are imported into the keystore
  • -out ssks.p12 – this is the keystore used by mqweb
  • -name “server”– this is the label given to the certificate in the keystore, used in serverKeyAlias in the mqweb xml configuration
  • -passin file:password.file -passout file:password.file – this gives the passwords to use

Other commands I used, to display information about the certificate

  • openssl x509 -purpose -in ss.pem -inform PEM -nocert
  • openssl x509 -in ss.pem -noout -ext subjectAltName
  • openssl x509 -in ss.pem -noout -ext keyUsage
  • openssl x509 -in ss.pem -noout -ext extendedKeyUsage

Update the mqweb configutation file

<keyStore id="defaultKeyStore" 
          location="/home/colinpaice/ssl/ssks.p12"  
          type="pkcs12" 
          password="password"/> 
<!-- this is used for authentication with user certificates
<keyStore id="defaultTrustStore" 
          location="/home/colinpaice/ssl/key.jks" 
          type="JKS" 
          password="zpassword"/>
-->
<ssl id="defaultSSLConfig" 
     keyStoreRef="defaultKeyStore" 
     serverKeyAlias="server" 
     clientAuthentication="false" 
     clientAuthenticationSupported="false" 
/>
<!--trustStoreRef="defaultTrustStore" sslProtocol="TLSv1.2"
-->

Stop mqweb

/opt/mqm/bin/endmqweb

Start mqweb

/opt/mqm/bin/strmqweb

Check /var/mqm/web/installations/Installation1/servers/mqweb/logs/messages.log for messages like

[14/01/20 09:12:15:730 GMT] 00000024 com.ibm.ws.ssl.config.WSKeyStore E CWPKI0033E: The keystore located at /home/colinpaice/ssl/ssks.p12 did not load because of the following error: keystore password was incorrect.

Import it into Chrome

If you do not import it into the web browser, the web browser will complain and give you the option to accept it as untrusted.  If this is just a test system this may be acceptable.  If you want to be able to trust the web server, you need to import the certificate into the browser’s keystore, as trusted.

I have several profiles for Chrome.  At one point it hickuped and created a new profile.

Find the keystore

In Chrome use the url chrome://version/ this gives the profile path, for example /home/colinpaice/snap/chromium/986/.config/chromium/Default

Remove the old certificate

certutil -D -d sql:/home/colinpaice/snap/chromium/986/.pki/nssdb -n server

  • certutil -D – delete the certificate
  • -d sql:/home/colinpaice/snap/chromium/986/.pki/nssdb – from this keystore directory
  • -n server with this name

Add the new certificate

certutil -A -d sql:/home/colinpaice/snap/chromium/986/.pki/nssdb -t “P,,” -n server -i $name.pem

  • certutil -A – add a certificate
  • -d sql:/home/colinpaice/snap/chromium/986/.pki/nssdb – into this keystore directory
  • -t “P,,” – give it these permissions.
    • P says Trusted Peer certificate.   The certificate appears in Chrome under “servers”
  • -n server – with this name
  • -i ss.pem – and this certificate

Tell Chrome to pickup the changes

Use the url chrome://restart to restart chrome

Try using it

use the url like https://127.0.0.1:9443/ibmmq/console/

You should get the IBM MQ Console – login

 

Certificates in Chrome

You can import certificates without using the certutil command.

You can display the certificates in Chrome using the url chrome://settings/certificates .

If you click on “Your certificates” or “Servers”, and then click on import, you can import a certificate.

I selected the directory, and then the ss.pem file.   The certificate ended up in “Others” under

org-aaaa

  • UNTRUSTED colinpaice

Use the url chrome://restart to restart chrome

Use the url like https://127.0.0.1:9443/ibmmq/console/

This gave me the “Your connection is not private”,  NET::ERR_CERT_AUTHORITY_INVALID.

The only way I found of making it trusted was to use the certutil command

certutil -L -d sql:/home/colinpaice/snap/chromium/986/.pki/nssdb

This listed the certificates in the store.   The one I had just added was colinpaice #2

certutil -M -d sql:/home/colinpaice/snap/chromium/986/.pki/nssdb -n “colinpaice #2” -t P,,

This modifies the certificate to be a Trusted Peer.  Restart Chrome, and the certificate appeared in the “Servers” section.

Using the mqweb url now worked successfully

Setting up a CA signed certificate for the mqweb server end

When using mqweb with certificates you can use

  • a self signed certificate to identify the server
  • a CA signed certificate to identify the server

You can use certificates to authenticate…

  • a self signed certificate at the client end
  • a CA signed certificate at the client end

This post explains how I set up mqweb to use a CA  signed certificate at the server, and to import the CA into my Chrome browser.

The steps are

  • Create your certificate authority certificate
  • Create the certificate request for mqweb server
  • Sign the request
  • Create the mqweb keystore and import the mqweb certificate
  • Import the CA into the web browser keystore if required

Create your certificate authority certificate

If you do not already have a certificate authority and a process for signing certificates you need to set these up.   To do it properly, you should create a certificate request and have an external CA sign it.

The following command creates a self signed certificate.   This is your CA authority certificate and private key.

openssl req -x509 -config openssl-ca.cnf -newkey rsa:4096 -subj “/C=GB/O=SSS/OU=CA/CN=SSCA” -nodes  -out cacert.pem -keyout cacert.key.pem -outform PEM

  • openssl req -x509 – create a self signed certificate request.  -x509 says self signed.
  • -config openssl-ca.cnf – use this file for the definitions
  • -newkey rsa:4096 – generate a new key
  • -nodes  – do not encrypt the private keys.  I do not know if this should be specified or not.
  • -subj “/C=GB/O=SSS/OU=CA/CN=SSCA” –  with this DN
  • -out cacert.pem – output the certificate.   This is used when signing.    This file is sent to all users.
  • -keyout cacert.key.pem – output the private key.  This is used when signing.  This files stays on the machine.
  • -outform PEM – in this format

In the config file, the important options I had were

[ req_extensions ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer
basicConstraints = critical,CA:TRUE, pathlen:0
keyUsage = keyCertSign, digitalSignature

You need to distribute the cacert.pem certificate to all your users, so they import it into their keystores.

Create the certificate request for mqweb server

The following command creates a certificate request which will be sent to the CA to sign.

openssl req -config mqwebserver.config -newkey rsa:2048 -out mqweb.csr -outform PEM -keyout mqweb.key.pem -subj “/C=GB/O=cpwebuser/CN=mqweb” -passin file:password.file -passout file:password.file

  • openssl req – as this request does not have -x509 specified it is for a certificate request
  • -config mqwebserver.config – use definitions in the specified  file
  • -newkey rsa:2048 – create a new  certificate request and private key with a 2048 bit  RSA key
  • -out mqweb.csr – use this output file for the request to be sent to the CA
  • -outform PEM – use pem format
  • -keyout mqweb.key.pem – put the private key in this file
  • -subj “/C=GB/O=cpwebuser/CN=mqweb” – with this distinguished name. It can have any values which meet your enterprise standards.
  • -passin file:password.file -passout file:password.file – use the passwords in the file(s).  The file:… says use this file. You can specify a password instead.  As the same file is used twice, two lines in the file are used.

In the config file, the important options were

[ req_extensions ]
subjectKeyIdentifier = hash
basicConstraints = CA:FALSE
subjectAltName = DNS:localhost, IP:127.0.0.1
nsComment = "OpenSSL mqweb server"
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = critical, serverAuth

Sign the request

Send the *.csr file to your CA.

Initial setup of ca signing process

If this is the first time you are using your CA you need to set up some files.  The files are referred to in the config file used by openssl ca command

touch index.txt
echo '01' > serial.txt

  • index.txt  is the certificate database index file.  This name is used in the config file option database =… .  For the format of this file see here. 
  • serial.txt contains the current serial number of the certificate. This name is used in the config file option serial =… .

Sign the certificate request

This takes the .csr file and signs it.

openssl ca -config casign.config -md sha384 -out mqweb.pem -cert cacert.pem -keyfile cacert.key.pem -infiles mqweb.csr

  • openssl ca – do the ca signing
  • -config casign.config – using the specified config file
  • -md sha384 – what message digest strength to use
  • -out mqweb.pem – put the signed certificate in this file
  • -cert cacert.pem – sign it with this ca file
  • -keyfile cacert.key.pem – sign it with this ca private  file
  • -infiles mqweb.csr – this is the input certificate request file

This displays the certificate, so check it is correct.  You get prompted

  • Sign the certificate? [y/n]:y
  • 1 out of 1 certificate requests certified, commit? [y/n]y

In the config file the important section is

[ ca_extensions ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
basicConstraints = CA:FALSE
keyUsage = keyEncipherment
extendedKeyUsage = serverAuth

Send the signed certificate back to the requestor.

Create the keystore to be used by mqweb and import the certificate

You can delete the certificate in the keystore using runmqckm -cert -delete -db mqweb.p12 -pw password -label mqweb .  This is not required.

openssl pkcs12 -export -inkey mqweb.key.pem -in mqweb.pem -out mqweb.p12 -CAfile cacert.pem -chain -name mqweb -passout file:password.file -passin file:password.file

This command creates the keystore (if requried) and imports the signed certificate and private key into the store with the specified name.   If a certificate exists with the same name, it is replaced.

  • openssl pkcs12 -export – this says a pkcs12 file will be created
  • -inkey mqweb.key.pem – using this private key file
  • -in mqweb.pem – and this signed certificate
  • -out mqweb.p12 – output put it to this pkcs12 keystore, used by mqweb
  • -CAfile cacert.pem – using this CA certificate
  • -chain – include all of the certificates needed when adding the certificate to the key store
  • -name mqweb – create this name in the keystore.  It is used to identify the key in the key store.
  • -passout file:password.file -passin file:password.file – use these password files

There is no config file for this operation.

Use chmod and chown to protect this keystore file from unauthorised access.

Change the mqweb configuration file.

<keyStore id="defaultKeyStore" 
          location="/home/colinpaice/ssl/mqweb.p12"  
          type="pkcs12" 
          password="password"/> 
<!-- the trust store is used when authenticating 
<keyStore id="defaultTrustStore" 
          location="/home/colinpaice/ssl/key.jks" 
          type="JKS" 
          password="zpassword"/>
-->
<ssl id="defaultSSLConfig" 
     keyStoreRef="defaultKeyStore" 
     serverKeyAlias="mqweb" 
     clientAuthentication="false" 
     clientAuthenticationSupported="false" 
/>
<!--trustStoreRef="defaultTrustStore" sslProtocol="TLSv1.2"
-->

The keystore name and server key alias which identifies which certificate to use,  are highlighted.

Stop mqweb

/opt/mqm/bin/endmqweb

Start mqweb

/opt/mqm/bin/strmqweb

Check /var/mqm/web/installations/Installation1/servers/mqweb/logs/messages.log for

Successfully loaded default keystore: /home/colinpaice/ssl/ssl2/mqweb.p12 of type: pkcs12.   This means it has successfully opened the keystore.

If you do not get this message use a command like grep ” E ” messages.log  and check for messages like

E CWPKI0033E: The keystore located at …. did not load because of the following error: keystore password was incorrect.

Import the CA certificate into Chrome

You need to do this once for every CA certificate

I have several profiles for Chrome.  At one point it hickup-ed and created a new profile, my scripts carried on updating the old profile until I realized a different profile was now being used.

Find the keystore

In Chrome use the url chrome://version/ this gives the profile path, for example /home/colinpaice/snap/chromium/986/.config/chromium/Default

You can remove the old certificate CA

certutil -D -d sql:/home/colinpaice/snap/chromium/986/.pki/nssdb -n myCACert

  • certutil -D – delete the certificate
  • -d sql:/home/colinpaice/snap/chromium/986/.pki/nssdb – from this keystore directory
  • -n  myCACertr with this name

Add the new CA certificate

certutil -A -d sql:/home/colinpaice/snap/chromium/986/.pki/nssdb -t “C,,”  -i cacert.pem -n myCACert

  • certutil -A – add a certificate
  • -d sql:/home/colinpaice/snap/chromium/986/.pki/nssdb – into this keystore directory
  • -t “C,,” – give it these permissions.
    • C says Trusted CA.   The certificate appears in Chrome under “certificate authorities”
  • -i cacert.pem – import this certificate
  • -n myCACert – with this name

Tell Chrome to pickup the changes

Use the url chrome://restart to restart chrome

Try using it.   Use the url like https://127.0.0.1:9443/ibmmq/console/

You should get the IBM MQ Console – login

Understanding the TLS concepts for using certificates to authenticate in mqweb.

This blog post gives background on setting up mqweb to use digital certificates. The IBM documentation in this area is missing a lot of information, and did not work for me.   I started documenting how to set up the certificates for the mqweb support, and found I was having to explain details of what was needed, before giving the command to do it.  I have also tried to cover it from a production environment, where you will use signed certificates, and automated deploy etc, instead of GUIs.   I suggest you read it before trying to set up mqweb with TLS .   Most of the content applies to the REST API as well as web browsers, but tools like CURL and Python  are much easier to set up and use.

If I have made mistakes (and it is easy to do so) or there are better ways of doing things,  please let me know.

It covers

  • How certificates are used
  • Different levels of mqweb security and authentication
  • How is mqweb security set up
    • The mqweb server end
    • At the web browser
  • How does the handshake work if certificates are being used?
  • Commands to issue REST commands to MQWEB
  • Setting up certificates.
    • Distinguished names
    • Certificate purpose for signed certificates
    • Self signed certificate
    • Strong protection
    • Certificates expire
  • Encrypting passwords in the config file
  • Which keystores should I use

How certificates are used

As part of the TLS handshake to do authentication, a certificate is send from the sender to the end user to identify the server. If you are doing authentication with certificates, a “client” certificate is sent up to the server providing information about the subject (person) and how the certificate can be used, for example for authentication or just providing encryption.

You can have “self signed” certificates and certificates signed by a certificate authority.

With self signed, you need a copy of the certificate at each end of the connection, so the certificate received from the client is checked with the server’s copy.  With more than one certificate, it quickly becomes impractical to use self signed certificates, and these would not be used in production. (Consider you have 100 partners you work with; you have 100 Linux servers you need to keep up to date; and on average, a certificate expires every week) . Also emailing a copy of the self signed certificate to a recipient is open to a “man in the middle” attack where your certificate is replaced with a bogus one, and so is not secure.  Self signed are fine for test systems.

The term Certificate Authority(CA)  is a term used for a chain of certificates which are used to sign other certificates.  If both ends share a common certificate, then the receiver can validate the payload.  Strictly, the CA owns the root certificate which certifies the rest of the chain.

With a signed certificate, a checksum of the certificate is encrypted by the signer, and appended to the certificate as part of the “signing process”. When the a certificate is sent to a recipient, it contains the certificate authority’s certificate. The recipient checks to make sure the certificate authorities match, then does the same calculation on the checksum and compares it with the value passed in the certificate. If they match the passed certificate is valid.
This means that the server only needs to have the certificate authority certificate chain in its trust  store, it does not need the individual client certificates.  Similarly when the server sends down the certificate to the browser, the browser does not need a copy of the certificate, just the CA chain.  If you change the certificate at the server end, you do not need to change the browser end.

This greatly simplifies the use of digital certificates, as you only need one certificate in the server, to identify the server, each user needs just one certificate and there is no emailing of certificates.

CA signed certificates are more secure than self signed certificates, and the validation has stronger checks.  A certificate has “extensions” which define how the certificate can be used, for example signing code, but not for authentication; it can be used to identify a server, but not an end user.

Certificates have a validate date range not-valid-before and not-valid-after. You need a process to renew certificates before they expire. This applies to the “client” certificate and the certificate authority certificate.

Certificate have a Distinquished Name, for example CN=colinpaice, OU=Test, O=IBM,C=GB. Where CN is Common Name, and is the user name, OU is Organization Unit, O is the Organization and C is the Country.

When I used curl with a self signed certificate I got

curl: (60) SSL certificate problem: self signed certificate in certificate chain
More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

If you use the curl – – insecure option  you avoid this message, and it works.

Different levels of mqweb security and authentication

There are different levels of security and authentication

  1. No TLS. Data flows between a web server and web browser in clear text.  This is not used by mqweb.
  2. The server sends a certificate to the web browser. This provides an encryption key for traffic. It also provides the URL of the web server.  For a CA signed certificate, the web browser then checks the URL coming from the web server, with the names in the certificate to make sure they match. This gives protection from a bad person trying to point your browser at their server using a different URL. If you are not using certificates to authenticate, you logon with userid and password.  Data flowing is encrypted using information sent down in the certificate.   This is used by mqweb.
  3. As 2), and in addition, a certificate is sent up from the client and used instead of entering a password and userid. This is configurable at the mqweb level.  The certificate is validated by the server, and the Common Name is used as the userid.  This means
    1. Every certificate needs a unique CN
    2. a password is not used
    3. DN:CN=colinpaice,O=SSS,OU=TEST,C=GB and DN:CN=colinpaice,O=SSS,OU=PROD,C=GB

would both be accepted for userid colinpaice if they both had the same CA.

In all cases the userid is checked with the information in the mqweb configuration xml file.

You can specify userids or groups in the xml file.  It is better to specify groups than userids as it is less administration. If a person joins a department, or leaves a department, then you just have to update the group, not all of the configuration files.

How is mqweb security set up?

The mqweb server end

The server’s certificate and private key is stored in a key store – this store will have one, and can have many certificates and private keys

The certificates used for client authentication are stored in the trust store.

For example with the definition in the mqwebuser.xml

<ssl id="defaultSSLConfig"
  keyStoreRef="defaultKeyStore" serverKeyAlias="colincert"
  trustStoreRef="defaultTrustStore"
  sslProtocol="TLSv1.2"
  clientAuthentication="true"
  clientAuthenticationSupported="true"
/>

The keyStoreRef=”defaultKeyStore” says look for the definition with defaultKeyStore. This will point to a key store. Use the certificate with the name defined in the serverKeyAlias

So with

<keyStore id="defaultKeyStore"
          location="/home/colinpaice/ssl/key.pkcs12"
          type="pkcs12"
          password="zpassword "/>

the keystore /home/colinpaice/ssl/key.pkcs12 with certificate colincert will be used.

The trustStoreRef=”defaultTrustStore” says look for the definition with defaultTrustSstore. This will point to the trust store.

With

<keyStore id="defaultTrustStore"
   location="/home/colinpaice/ssl/key.jks"
   type="JKS"
   password="zpassword"/>

the trust store at location /home/colinpaice/ssl/key.jks will be used.

This needs to have the CA certificates, and any self signed certificates.

At the web browser

The web browser needs to have the self signed certificate or the CA certificate, for the certificate which is sent to the browser as part of the handshake “Hello I am the server”, so it can be validated.  If the certificate cannot be validated,  for example there was no copy of the self signed certificate, the browser will notify you and may allow you to accept the risk.   This is insecure, and ok for a test environment.

If certificates are to be used for authentication, then the web browser also needs the user’s certificate and private key, along with with any CA certificates.

How does the handshake work if certificates are being used?

The web server extracts the specified certificate from the keystore and sends it to the web browser.

The certificate is validated either with the browser’s self signed copy, or with the browser’s copy of the CA certificates.

For a signed certificate, the url from the web server is checked with the names in the “Certificate Subject Alternate Name” extension within the certificate. For example IP:127.0.0.1

If client authentication is used, the certificates are read from the server’s trust store. The DN of the self signed certificates and the DN of the CA certificates are extracted and sent down to the browser.

The browser takes this list and checks through the “user” certificates in its key store, for those self signed certificates with a matching DN, or those certificates which have been signed by the CA.

The list of matching certificates is displayed for the user to select from.
For example

If the mqweb server trust store had

  • CN=colinpaice,ou=SSS1,o=SSS,C=GB self signed
  • CN=CA,O=SSS,C=GB Certificate Authority

and the browser’s keystore had

  • CN=colinpaice,ou=SSS1,o=SSS,C=GB self signed
  • CN=colinpaice1,ou=ZZZZ,o=SSS,C=GB self signed
  • CN=colinpaice2,ou=signed,o=SSS,C=GB signed by CN=CA,O=SSS,C=GB
  • CN=colinpaice3,ou=signed,o=ZZZ,C=GB signed by CN=CA,O=ZZZ,C=GB

the list displayed to the user would indicate the following certificates

  • CN=colinpaice,ou=SSS1,o=SSS,C=GB
  • CN=colinpaice2,ou=signed,o=SSS,C=GB

The Chrome and Firefox remember this decision until the browser is restarted, so if you want to change to use a different certificate – tough; you have to restart the browser.

The browsers use a keystore which you can access through the browser or commands like certutil or pk12util.

Commands to issue REST commands to MQWEB

If you use commands like curl, you can specify the certificate authority file, the user certificate, and the user private key using parameters. You do not need a keystore.  For example 3 .pem files are used, one for the certificate, one for the private key and one for the CA certificates.

curl –cacert ./cacert.pem –cert ./colinpaice.pem:password –key colinpaice.key.pem https://127.0.0.1:9443/ibmmq/rest/v1/admin/qmgr

If you use python requests package you can issue “requests” and again specify the various files needed for the certificates.

Setting up certificates.

It is fairly complicated setting up certificates as there are many options.

Distinguished names

Your organization will have standards you need to conform to. For example

The Distinquished Name (eg CN=colinpaice,ou=test,o=SSS,C=GB). Organisation is usually your enterprise name, OU could be department name, CN could be userid or other name. You can set up MQ channels to restrict the DN for example to containing ou=test,o=SSS,C=GB.

I set up a DN with C=GB,O=cpwebuser,CN=colinpaice. If I look at the certificate it has CN = colinpaice, O = cpwebuser, C = GB – in a different order.

If I look in the browser’s keystore, the certificates show up under the “O” value, so under “org-cpwebuser”.

As the CN is used as the userid, make sure it is the same case. On my linux machine my userid is colinpaice, the CN must be colinpaice.

Certificate purpose for signed certificates

If you create a certificate signed by a CA (even your private CA) the following checks are done during the TLS handshake.

  • The certificate has been signed with “serverAuth” to allow it to be used to authorise servers.
  • The key usage has  been signed with “Authentication”
  • The certificate has the IP address of the server.

If any one of these fail, the handshake fails.

A certificate can be used for many purposes, for example signing code, signing certificates (by a certificate authority). These properties are defined when the certificate is signed.

Both client and server certificates needs keyUsage = digitalSignature.

The Extended Key Usage (EKU) indicates the purpose, or what the certificate public key can be used for.

  • A client certificate needs extendedKeyUsage = clientAuth
  • A server certificate needs extendedKeyUsage = serverAuth.

The command openssl x509 -purpose -in colinpaice.pem -inform PEM -nocert gave

Certificate purposes:

  • SSL client : Yes
  • SSL client CA : No
  • SSL server : No
  • SSL server CA : No

So we can see this has clientAuth key usage.

If these are not set up properly  you can get errors about unauthorized access and “SSLHandshakeException: null cert chain” errors.

use openssl x509 -in colinpaice.pem -noout -text |less
and search for Usage

This gave me

X509v3 Key Usage: 
   Digital Signature
X509v3 Extended Key Usage: 
   TLS Web Client Authentication

 

Self signed certificate

A self signed certificate is considered weaker than a signed certificate, and some of the checks are not done.

If you are using a self signed certificate, the certificate needs keyUsage = digitalSignature, keyCertSign , it does not need  the IP address of the server, nor extendedKeyUsage.

It needs to be installed into the browser keystore as Trusted.  If it is not flagged as trusted, then the browsers give errors, and may allow you to continue if you accept it the risk.

Strong protection

There are different strengths of encryption. Stronger ciphers take longer to break. Some encryption or hashing techniques are considered weak, and may not be accepted. For example SHA1 is weak (some browsers will not accept it), SHA256 and SHA348 are much stronger.

Some encryption can be offloaded to specialized chips, so have a smaller CPU cost. You need to use your enterprise standard levels of encryption and hashing.

Certificates expire

All certificates (user and CA) have a valid date range. If they are used beyond their end date, you will get an error, and it will not work. You need to have a process in place to renew certificate, including CA certificates.  If you use an external CA, it can take days to get a new certificate and deploy it.

Keystores

Some processing need a keystore.  For example Firefox and Chrome use a nss format keystore.  The mqweb server needs a keystore to store the certificate to identify the server, and can use a truststore to contain remote authentication certificates.

There are a variety of tools to manage keystores.  IBM provide GUI interfaces such as strmqikm, and a command line interfaces runmqikm.   There is keytool from Oracle, and other tools such as openssl, pkcs12 and certutil.

There are different sorts of keystores

  • nssdb – used by browsers to store keys
  • pkcs12 has certificates and the  private key
  • cms  contains keys certificate etc
  • jks – Java keystore  – used by java to contain certificates

Certificates can be in different formats

  • .pem this is a certificate encoded in base 64 encoding.   This may look like
-----BEGIN CERTIFICATE-----
MIIDfzCCAmegAwIBAgIURubFS5yEwZYi//7Qx0kTmX/LnMUwDQYJKoZIhvcNAQEL
...
-----END CERTIFICATE-----
  • .der this is a binary format

I found it easiest to create certificates using openssl, and import them into the keystores, rather than use a GUI and then export them.  This means it it can be scripted and automated, and requires less work.

Encrypting passwords in the config file

Keystores usually have a password.

For example in the mqwebuser.xml file is

<keyStore id="defaultTrustStore"
    location="/home/colinpaice/ssl/key.jks" 
    type="JKS"
    password="zpassword"/>

This password can encrypted using the /opt/mqm/web/bin/securityUtility command. See here.

For example to encrypt the string “zpassword”

/opt/mqm/web/bin/securityUtility encode –encoding=aes zpassword gives

{aes}AJOmiC8YKMFZwHlfJrI2//f2Keb/nGc7E7/ojSj37I/5

doing it again gave a different value

{aes}AMsUYgpOjy+rxR7f/7wnAfw1gZNBdpx8RpxfwjeIG8Wj

Your mqwebuser.xml file would then have

<keyStore id="defaultTrustStore"
    location="/home/colinpaice/ssl/key.jks" 
    type="JKS"
    password="{aes}AMsUYgpOjy+rxR7f/7wnAfw1gZNBdpx8RpxfwjeIG8Wj"/>

Which keystores should I use?

I used openssl to define and manage my certificates, because the IBM tools did not have all of the capabilities.

I used a pkcs12 (.pkcs12 or .p12) store for the keystore and a jks(.jks) store for the trust store.

Firefox and Chrome use a nssdb (Netscape) database.   I used tools pkcs12 to insert certificates, and certutil to display and manage the database.