Authenticating an SSL telemetry connection using self-signed certificates

Use self-signed certificates generated using Keytool to authenticate an SSL connection. You have the option of authenticating the telemetry channel, or the telemetry channel and the clients that attach to it. Messages flowing on the connection are encrypted.

Before you begin

Do the task, Creating your first MQ Telemetry Transport publisher application using Java before you start, to get PubSync.java working with an unsecured TCP/IP connection. In this task, you modify PubSync.java to work with an SSL connection.

About this task

The steps in the task are written as a programming exercise. You must adapt the procedure to perform real authentication in a production environment.

The task is written for Windows. Change the directory paths for Linux®.

Procedure

  1. Do the task, Modifying PubSync.java to use SSL, to modify PubSync.java to use SSL.
  2. Configure the telemetry channel, and create the keystores to use SSL.

    Authenticate just the telemetry channel, or the channel and clients that connect to it:

  3. Stop and restart the telemetry (MQXR) service to pick up changes to telemetry channel configurations.
  4. Run the client program to see if the configuration works.

Modifying PubSync.java to use SSL

Modify the first publisher program example to connect to a telemetry channel using SSL. Set the SSL properties used by the modified program.

Before you begin

You are assumed to have installed the MQTT v3 client jar files, Javadoc, Eclipse, configured telemetry channels and coded and run PubSync.java before performing this task. You have an Eclipse workspace that includes a running version of PubSync.java.

About this task

The task uses the publisher client, PubSync.java, you created in Creating your first MQ Telemetry Transport publisher application using Java as a base. Only small modifications are necessary to use SSL; see Figure 1 and Figure 2.

Procedure

  1. Make a copy of PubSync.java in the com.ibm.mq.id package, and name the copy PubSyncSSL.java.

    See Creating your first MQ Telemetry Transport publisher application using Java for the steps to create PubSync.java in the com.ibm.mq.id package.

  2. Set Example.SSLAddress to the socket address of the telemetry channel you have configured to use for the SSL configuration.
  3. Change the socket address parameter of the client constructor to use Example.SSLAddress.
    MqttClient client = new MqttClient(Example.SSLAddress, Example.clientId);
    
  4. Set the MqttConnectOptions.SSLProperties in PubSyncSSL.java, and pass MqttConnectOptions as a parameter of MqttClient.connect.
    MqttConnectOptions conOptions = new MqttConnectOptions();
    conOptions.setSSLProperties(Example.getSSLSettings());      
    client.connect(conOptions);

    See the italicized code PubSyncSSL.Java using the constants set in Example.java.

Examples

The modifications to PubSync.java to add SSL are shown in Figure 1 in italics.
Figure 1. PubSyncSSL.Java
package com.ibm.mq.id;
import com.ibm.micro.client.mqttv3.*;
public class PubSyncSSL {
  public static void main(String[] args) {
    try {
      MqttClient client = new MqttClient(Example.SSLAddress, Example.clientId);
      MqttTopic topic = client.getTopic(Example.topicString);
      MqttMessage message = new MqttMessage(Example.publication.getBytes());
      message.setQos(Example.QoS); 
      MqttConnectOptions conOptions = new MqttConnectOptions();
      conOptions.setSSLProperties(Example.getSSLSettings());
      client.connect(conOptions);
      System.out.println("Waiting for up to " + Example.sleepTimeout / 1000
              + " seconds for publication of \"" + message.toString() 
              + "\" with QoS = " + message.getQos());
      System.out.println("On topic \"" + topic.getName() + "\" for client instance: \""
              + client.getClientId() + "\" on address " + client.getServerURI() + "\"");
      System.out.println("SSL Properties" + conOptions.getSSLProperties());
      MqttDeliveryToken token = topic.publish(message);
      token.waitForCompletion(Example.sleepTimeout);
      System.out.println("Delivery token \"" + token.hashCode()
          + "\" has been received: " + token.isComplete());
      client.disconnect();
    } catch (Exception e) {
      System.out.println("Client exception caught");
      e.printStackTrace();
    }
  }
}
The modifications to Example.java are shown in Figure 2.
Figure 2. Modifications to Example.java
 public static final String          SSLAddress = 
    System.getProperty("SSLAddress", "ssl://localhost:8883");

 public static final Properties getSSLSettings() {
    final Properties properties = new Properties();
    properties.setProperty("com.ibm.ssl.keyStore", "C:\\Certificates\\SSClientKey.jks");
    properties.setProperty("com.ibm.ssl.keyStoreType", "JKS");
    properties.setProperty("com.ibm.ssl.keyStorePassword", "password");
    properties.setProperty("com.ibm.ssl.trustStore", "C:\\Certificates\\SSClientTrust.jks");
    properties.setProperty("com.ibm.ssl.trustStoreType", "JKS");
    properties.setProperty("com.ibm.ssl.trustStorePassword", "password");
    return properties;

Authenticating the telemetry channel

Clients authenticate the telemetry channel to encrypt the contents of the messages flowing on the channel, and to ensure a client connects to the correct telemetry channel. The server does not authenticate the client.

About this task

You can use a number of different keystore editors to create and manage self-signed certificates. The task uses the command line keytool command, which is part of the JRE. You can use the GUI tool iKeyman, which is shipped with WebSphere MQ to browse keystores and generate keys. Launch iKeyman using the command strmqikm.

Procedure

  1. Create a telemetry channel, SSLSSOptClients that requires an SSL connection using the New telemetry channel wizard. The channel accepts anonymous clients.

    Adapt your channel configuration from the following configuration stanza. Do not edit the telemetry properties file directly; use the wizard.

    com.ibm.mq.MQXR.channel/SSLSSOptClients: \
    com.ibm.mq.MQXR.Port=8883;\
    com.ibm.mq.MQXR.Backlog=4096;\
    com.ibm.mq.MQXR.KeyFileName=C:\\Certificates\\SSServerOptKey.jks;\
    com.ibm.mq.MQXR.PassPhrase=password;\
    com.ibm.mq.MQXR.ClientAuth=OPTIONAL;\
    com.ibm.mq.MQXR.UserName=Admin;\
    com.ibm.mq.MQXR.StartWithMQXRService=true
  2. Generate the keys for client to authenticate the telemetry channel.
    1. Generate a self-signed key-pair for the telemetry channel in a new keystore, SSServerOptKey.jks:
      Keytool -genkey -noprompt -alias SSServerPrivate 
              -dname "CN=mqttserver.ibm.com, OU=ID, O=IBM, L=Hursley, S=Hants, C=GB" 
              -keystore SSServerOptKey.jks -storepass password -keypass password
    2. Export its public certificate as an ASCII file, using the -rfc option:
      Keytool -export -noprompt -alias SSServerPrivate -file SSServerPublic.cer 
              -keystore SSServerOptKey.jks -storepass password -rfc

      If you are running the task on windows, double-click SSServerPublic.cer to inspect its contents.

    3. Import the public certificate into a new client truststore, SSClientTrust.jks:
      Keytool -import -noprompt -alias SSServerPublic -file SSServerPublic.cer  
              -keystore SSClientTrust.jks -storepass password
    4. Create an empty client keystore, SSClientKey.jks.
      Keytool does not have a command to create an empty keystore. You have two choices:
      1. Run strmqikm, and create a keystore, SSClientKey.jks, but do not add any keys.
      2. Perform step 3a in Authenticating the telemetry channel and clients, but do not use the keys yet.

Authenticating the telemetry channel and clients

Clients authenticate the telemetry channel and the telemetry channel authenticates clients attaching to it. Messages flowing on the channel are encrypted.

About this task

You can use a number of different keystore editors to create and manage self-signed certificates. The task uses the command line keytool command, which is part of the JRE. You can use the GUI tool iKeyman, which is shipped with WebSphere MQ to browse keystores and generate keys. Launch iKeyman using the command strmqikm.

The telemetry channel is configured with a different keystore to the task, Authenticating the telemetry channel. You can use the same keystore, and omit step 2 to add keys to the keystore.

Procedure

  1. Create a telemetry channel, SSLSSReqClients that requires an SSL connection using the New telemetry channel wizard. The channel accepts only authenticated clients.

    Adapt your channel configuration from the following configuration stanza:

    com.ibm.mq.MQXR.channel/SSLSSReqClients: \
    com.ibm.mq.MQXR.Port=8884;\
    com.ibm.mq.MQXR.Backlog=4096;\
    com.ibm.mq.MQXR.KeyFileName=C:\\Certificates\\SSServerReqKey.jks;\
    com.ibm.mq.MQXR.PassPhrase=password;\
    com.ibm.mq.MQXR.ClientAuth=REQUIRED;\
    com.ibm.mq.MQXR.UserName=Admin;\
    com.ibm.mq.MQXR.StartWithMQXRService=true
  2. Generate the keys for client to authenticate the telemetry channel.
    1. Generate a self-signed key-pair for the telemetry channel in a new keystore, SSServerReqKey.jks:
      Keytool -genkey -noprompt -alias SSServerPrivate 
              -dname "CN=mqttserver.ibm.com, OU=ID, O=IBM, L=Hursley, S=Hants, C=GB" 
              -keystore SSServerReqKey.jks -storepass password -keypass password
    2. Export its public certificate as an ASCII file, using the -rfc option:
      Keytool -export -noprompt -alias SSServerPrivate -file SSServerPublic.cer 
              -keystore SSServerReqKey.jks -storepass password -rfc

      If you are running the task on windows, double-click SSServerPublic.cer to inspect its contents.

    3. Import the public certificate into a new client truststore, SSClientTrust.jks:
      Keytool -import -noprompt -alias SSServerPublic -file SSServerPublic.cer  
              -keystore SSClientTrust.jks -storepass password
  3. Generate the keys for the telemetry channel to authenticate a client.
    1. Generate a self-signed key-pair for the client in a new keystore, SSClientKey.jks:
      Keytool -genkey -noprompt -alias SSClientPrivate 
              -dname "CN=mqttclient.ibm.com, OU=ID, O=IBM, L=Hursley, S=Hants, C=GB" 
              -keystore SSClientKey.jks -storepass password -keypass password
    2. Export its public certificate as an ASCII file, using the -rfc option:
      Keytool -export -noprompt -alias SSClientPrivate -file SSClientPublic.cer 
              -keystore SSClientKey.jks -storepass password -rfc

      If you are running the task on windows, double-click SSClientPublic.cer to inspect its contents.

    3. Import the public certificate into the server keystore, SSServerReqKey.jks:
      Keytool -import -noprompt -alias SSClientPublic -file SSClientPublic.cer  
              -keystore SSServerReqKey.jks -storepass password

      Telemetry channels use the same store for both private keys and trusted certificates.