Skip to content

Connecting devices to MindConnect IoT Extension - using Trusted Certificates

Devices can authenticate against MindConnect IoT Extension using X.509 client certificates. Devices can communicate using the MQTT interface of the platform, however, MQTT over WebSocket is not supported. MindConnect IoT Extension expects devices to connect using SSL on port 8883. Each tenant individually defines whom it trusts by uploading the base CA certificate. Devices connecting to the platform with certificates are not required to provide the tenant ID, username, and password - authentication information will be obtained from the certificates.

This guide describes the step-by-step procedure to prepare and use Trusted Certificates in order to connect devices to MindConnect IoT Extension. For a detailed introduction of Trusted Certificates, see Introduction to X.509 certificates.

General Information

Execution Duration: 30 minutes
Tested with MindSphere version: Release 8th October 2018

Prerequisites

  • A MindSphere account.
  • Established MQTT connection to MindSphere. For more information, see Integrating MQTT.
  • The CA certificate may also be a self-signed certificate.
  • Certificates must be uploaded as X.509 version 3 certificates.
  • Uploaded certificates have to have set BasicConstraints:[CA:true].
  • Devices need to trust the MindConnect IoT Extension server certificate.
  • Certificates used by devices must contain the full certificate chain, including the uploaded CA certificate.
  • Certificates used by devices must be signed either by uploaded CA certificates or by a chain of certificates signed by uploaded CA certificates.
  • To generate certificates, ensure to have the OpenSSL toolkit installed.

Preparing Trusted Certificates

Creating a self-signed CA certificate

To create a self-signed CA certificate, proceed as follows:

  1. Create a directory for the root certificate and the signing configuration, for example: mkdir /home/user/Desktop/caCertificate
  2. Navigate to the created directory and create a configuration file for the CA certificate: touch caConfig.cnf
  3. Create a database file for keeping the history of certificates signed by the CA: touch database.txt
  4. Create a serial file with initial serial number, which will be used to identify signed certificates. After assigning this serial to the signed certificate, the value in this file will be automatically incremented: echo 1000 > serial
  5. Create subdirectories for signed certificates and the certificate revocation list: mkdir deviceCertificates crl
  6. Fill in the configuration file. Given below is an example configuration, which can be used for testing after changing the directory dir to your own. Consult a security specialist incase it must be used in the production environment:

    [ ca ]
    default_ca = CA_default
    [ CA_default ]
    # Directory and file locations.
    dir               = /home/user/Desktop/caCertificate
    certs             = $dir # directory where the CA certificate will be stored.
    crl_dir           = $dir/crl # directory where the certificate revocation list will be stored.
    new_certs_dir     = $dir/deviceCertificates # directory where certificates signed by CA certificate will be stored.
    database          = $dir/database.txt # database file, where the history of the certificates signing operations will be stored.
    serial            = $dir/serial # directory to the file, which stores next value that will be assigned to signed certificate.
    # The CA key and CA certificate for signing other certificates.
    private_key       = $dir/caKey.pem # CA private key which will be used for signing certificates.
    certificate       = $dir/caCert.pem # CA certificate, which will be the issuer of signed certificate.
    default_md        = sha256 # hash function
    default_days      = 375 # default number of days for which the certificate will be valid since the date of its generation.
    preserve          = no # if set to 'no' then it will determine the same order of the distinguished name in every signed certificate.
    policy            = signing_policy # the name of the tag in this file that specifies the fields of the certificate. The fields have to be filled in or even match the CA certificate values to be signed.
    # For certificate revocation lists.
    crl               = $crl_dir/caCrl.pem # CA certificate revocation list
    crlnumber         = $crl_dir/crlnumber # serial, but for the certificate revocation list
    crl_extensions    = crl_ext # the name of the tag in this file, which specifies certificates revocation list extensions, which will be added to the certificate revocation by default.
    default_crl_days  = 30 # default number of days for which the certificate revocation list will be valid since the date of its generation. After that date it should be updated to see if there are new entries on the list.
    [ req ]
    default_bits        = 4096 # default key size in bits.
    distinguished_name  = req_distinguished_name # the name of the tag in this file, which specifies certificates fields description during certificate creation and eventually set some default values.
    string_mask         = utf8only # permitted string type mask.
    default_md          = sha256 # hash function.
    x509_extensions     = v3_ca # the name of the tag in this file, which specifies certificates extensions, which will be added to the created certificate by default.
    # descriptions and default values of the created certificate fields.
    [ req_distinguished_name ]
    countryName                     = Country Name (2 letter code)
    stateOrProvinceName             = State or Province Name
    localityName                    = Locality Name
    organizationName                = Organization Name
    organizationalUnitName          = Organizational Unit Name
    commonName                      = Common Name
    emailAddress                    = Email Address
    # A default value for each field can be set by adding an extra line with field name and postfix "_default". For example: "countryName_default = PL". If you add this line here, then leaving country name empty during certificate creation will result in the value "PL" being used. If the default value was specified there, but during certificate creation you do not want to use this value, then instead use "." as the value. It will leave the value empty and not use the default.
    # default extensions for the CA certificate.
    [ v3_ca ]
    subjectKeyIdentifier = hash # subject key value will be calculated using hash funtion. It's the recommended setting by PKIX.
    authorityKeyIdentifier = keyid:always,issuer # The subject key identifier will be copied from the parent certificate. It's the recommended setting by PKIX.
    basicConstraints = critical, CA:true, pathlen:10 # "critical" specifies that the extension is important and has to be read by the platform. CA says if it is the CA certificate so it can be used to sign different certificates. "pathlen" specifies the maximum path length between this certificate and the device certificate in the chain of certificates during authentication. Path length is set here only to show how it is done. If you do not want to specify max path length, you can keep only the "basicConstraints = critical, CA:true" part here.
    keyUsage = digitalSignature, cRLSign, keyCertSign # specifies permitted key usages.
    # Default extensions for the device certificate. This tag is not used directly anywhere in this file, but will be used from the command line to create signed certificate with "-extensions v3_signed" parameter.
    [ v3_signed ]
    subjectKeyIdentifier = hash
    authorityKeyIdentifier = keyid,issuer
    basicConstraints = critical, CA:false
    keyUsage = nonRepudiation, digitalSignature, keyEncipherment
    # default extensions for certificate revocation list
    [ crl_ext ]
    authorityKeyIdentifier=keyid:always
    # Policy of certificates signing. It specifies which certificate fields have to be filled in during certificate creation. There are three possible values here:
    # "optional" - field value can be empty
    # "supplied" - field value must be filled in
    # "match" - signed certificate field value must match the CA certificate value to be created
    [ signing_policy ]
    countryName             = optional
    stateOrProvinceName     = optional
    organizationName        = optional
    organizationalUnitName  = optional
    commonName              = supplied # every certificate should have a unique common name, so this value should not be changed.
    emailAddress            = optional
    
  7. Create a private key with aes256 encryption and a length of at least 2048 bits. Also, a request to set the password will be made for the key during its creation: openssl genrsa -aes256 -out caKey.pem 4096

  8. Create a self-signed certificate using specifications from the configuration file. The “days” parameter says how long this certificate will be valid since the generation, so set it as desired: openssl req -config caConfig.cnf -key caKey.pem -new -x509 -days 7300 -sha256 -extensions v3_ca -out caCert.pem
  9. Print the created certificate with the command: openssl x509 -noout -text -in caCert.pem

Creating an intermediate certificate

The intermediate certificate is signed by the CA certificate; however, it can also be used to sign device certificates. An intermediate certificate is not required if one common CA certificate is used to sign all the device certificates, therefore, this step can be skipped. However, if some certificates are needed between the CA certificate and the device certificate, then an intermediate certificate must be created.

Note

In MindConnect IoT Extension, the maximum length of the chain of certificates is currently restricted to 2, and therefore, it is not possible to use any intermediate certificate between the CA certificate and the device certificate.

To create an intermediate certificate, proceed as follows:

  1. Create a new directory for intermediate certificates inside the caCertificate path: mkdir intermediateCertificate
  2. Navigate to this directory and create a configuration file for the intermediate certificate: touch intermediateConfig.cnf
  3. Create a database file for keeping the history of certificates signed by the intermediate certificate: touch database.txt
  4. Create a serial file with initial serial number, which will be used to identify signed certificates: echo 1000 > serial
  5. Create subdirectories for the signed certificates and the certificate revocation list: mkdir deviceCertificates crl
  6. Fill in the configuration file as in the CA configuration and change the general directory (dir) to the intermediateCertificate folder. Also, change private_key, certificate and crl names from current with “ca” prefix to “intermediate” prefix (for example: caKey.pem -> intermediateKey.pem), because files with this prefix will be generated in the next steps.
  7. Generate a private key for the intermediate certificate: openssl genrsa -aes256 -out intermediateKey.pem 4096
  8. Generate a certificate signing request: openssl req -config intermediateConfig.cnf -new -sha256 -key intermediateKey.pem -out intermediateCsr.pem
  9. Navigate to the caCertificate directory and generate a signed intermediate certificate. The CA configuration should be used here, because the private key specified in the configuration file will be used to sign the certificate: openssl ca -config caConfig.cnf -extensions v3_ca -days 3650 -notext -md sha256 -in intermediateCertificate/intermediateCsr.pem -out intermediateCertificate/intermediateCert.pem
  10. Verify if the generated certificate is correctly signed by CA: openssl verify -CAfile caCert.pem intermediateCertificate/intermediateCert.pem

Creating a device certificate signed by CA or intermediate

To create device certificate , proceed as follows:

  1. Navigate to the directory of the caCertificate or intermediateCertificate depending on which one is used to sign the device certificate.
  2. Generate the private key for the new certificate: openssl genrsa -aes256 -out deviceCertificates/deviceKey.pem 4096
  3. Generate the certificate signing request (change “caConfig.cnf” to “intermediateConfig.cnf” if you are in the intermediateCertificate directory): openssl req -config caConfig.cnf -new -sha256 -key deviceCertificates/deviceKey.pem -out deviceCertificates/deviceCsr.pem The commonName of the device certificate, which will be requested to provide in the console, must match the ClientId of the device during the connection.
  4. Generate the certificate signed by the CA or intermediate (change “caConfig.cnf” to “intermediateConfig.cnf” if you are in the intermediateCertificate directory): openssl ca -config caConfig.cnf -extensions v3_signed -days 365 -notext -md sha256 -in deviceCertificates/deviceCsr.pem -out deviceCertificates/deviceCert.pem
  5. Verify if the generated certificate is correctly signed by CA or intermediate (change “caCert.pem” to “intermediateCert.pem” if you are in the intermediateCertificate directory): openssl verify -partial_chain -CAfile caCert.pem deviceCertificates/deviceCert.pem

Creating the chain of certificates

To create a chain of certificates, navigate to the caCertificate directory:

  • If the CA certificate was created, which was used to sign the intermediate certificate and then the intermediate certificate was used to sign the device certificate, then create the chain of certificates using the command: cat intermediateCertificate/deviceCertificates/deviceCert.pem intermediateCertificate/intermediateCert.pem caCert.pem > intermediateCertificate/deviceCertificates/deviceCertChain.pem
  • If an intermediate certificate is not used, then use the command: cat deviceCertificates/deviceCert.pem caCert.pem > deviceCertificates/deviceCertChain.pem
  • If multiple intermediate certificates are being used between the CA certificate and the device certificate, then ensure to maintain the correct order during the chain creation. That is, every certificate has to be followed by the certificate, which it is signed by.

Creating keystore and truststore

  1. Navigate to the deviceCertificates directory with the device’s private key and the generated chain of certificates. If an intermediate certificate is being used between the CA certificate and the device certificate then it will be the caCertificate/intermediateCertificate/deviceCertificates path, otherwise it will be caCertificate/deviceCertificates. Create keystore using the generated chain of certificates and the private key of the device: openssl pkcs12 -export -name devicekeyentry -inkey deviceKey.pem -in deviceCertChain.pem -out deviceKeystore.pkcs12
  2. If the keystore must be converted to JKS format, then it is required to have the Java Keytool which is usually downloaded together with Java Development Kit: keytool -importkeystore -srckeystore deviceKeystore.pkcs12 -srcstoretype PKCS12 -destkeystore deviceKeystore.jks -deststoretype JKS
  3. If the server certificate is not available, it can be made available by the command: openssl s_client -showcerts -connect <mindsphere url>:<mqtt mutual ssl port (currently 8883, but that can be changed in the future)> | openssl x509 -outform PEM > serverCertificate.pem
  4. Now a truststore can be created, which will contain the server certificate. It has to be created with Java Keytool (openssl does not support creating truststore, so if the Java keytool is not used, then it is required to keep every trusted certificate in a separate pem file). Remember that the alias is the unique identifier for every keystore or truststore entry. It means that it is required to add a second trusted certificate to the same truststore and then change the alias from servercertificate in the command below to some other name:
    • In PKCS12 format: keytool -importcert -noprompt -keystore deviceTruststore.pkcs12 -alias servercertificate -file serverCertificate.pem
    • In JKS format: keytool -import -file serverCertificate.pem -alias servercertificate -keystore deviceTruststore.jks
  5. Optionally, instead of creating a new file for the truststore, it is possible to add the trusted certificates to the created keystore and store everything in one file, which is not the recommended solution:
    • If the keystore is in the PKCS12 format: keytool -importcert -noprompt -keystore deviceKeystore.pkcs12 -alias servercertificate -file serverCertificate.pem
    • If the keystore is in the JKS format: keytool -import -file serverCertificate.pem -alias servercertificate -keystore deviceKeystore.jks
  6. Check the content of your keystore (or truststore) with the command: keytool -list -v -keystore deviceKeystore.jks

Testing certificates with MQTT.fx client

  1. Generate a keystore and a truststore as described in Preparing Trusted Certificates if not already done.
  2. Upload the CA (or intermediate) certificate to the platform. This operation will add the uploaded certificate to the server’s truststore. It can be done in two ways, via User Interface and via REST.

Via User Interface

To add a certificate via User Interface, see Section Trusted certificates in MindConnect IoT Extension System Manual.

Via REST

To add a certificate via REST, proceed as follows:

  1. Display the CA (or intermediate) certificate, which is required to upload to the MindConnect IoT Extension and copy its PEM value, which starts with —–BEGIN CERTIFICATE—– and ends with —–END CERTIFICATE—– (including the hyphens). Remove new line symbols (\n) if they were added automatically at the end of each line: openssl x509 -in caCert.pem -text.

  2. Send it to the platform via POST request:

    Required role: ROLE_TENANT_ADMIN
    
    POST /tenant/tenants/<TENANT_ID>/trusted-certificates
    Host: https://<TENANT_DOMAIN>/
    Authorization: Basic <YOUR_AUTHENTICATION>
    Content-Type: application/json
    {
        "status" :  "ENABLED",
        "name" : "certificateName",
        "autoRegistrationEnabled" : "true",
        "certInPemFormat" : "<CERT_PEM_VALUE>"
    }
    
  3. Download and install the newest MQTT.fx client.

  4. In MQTT.fx, click “Extras” at the top and then “Edit Connection Profiles”.
  5. Insert the MindSphere URL in the “Broker address” line.
  6. Insert the SSL port in the “Broker port” line.
  7. In the “Client ID” field, insert the common name of the device certificate.
  8. Select "SSL/TLS" as the authentication type.
  9. Click “Enable SSL/TLS”.
  10. Select “TLSv1.2 protocol”.
  11. Select “Self signed certificates in keystores”.
  12. In the “Keystore File” field, insert the path to the deviceTruststore file with either JKS or PKCS12 format.
  13. In the “Trusted Keystore Alias” field, insert “servercertificate” or a different value if you provided a different alias in step 3 above.
  14. In the “Trusted Keystore Password” field, insert the password, which is created during the deviceTruststore file creation.
  15. In the “Client Keystore” field, insert the path to the deviceKeystore file with either JKS or PKCS12 format.
  16. In the “Client Keystore Password” field, insert the password created during the deviceKeystore creation.
  17. In the “Client KeyPair Alias” field, insert “devicekeyentry” or a different value if you provided a different alias in the “-name” parameter during the keystore creation.
  18. In the “Client KeyPair Password” field, insert the password, which is created during the deviceKey.pem creation.
  19. Check the “PEM formatted” field.
  20. Save and close the settings.
  21. Select the edited profile and click connect.

The connection is successful, and the buttons “Disconnect”, “Publish” and “Subscribe” are active now. That is, the connection with the certificates works correctly. The connection settings should look like this:

MCIOT device info

Any questions left?

Ask the community


Except where otherwise noted, content on this site is licensed under the MindSphere Development License Agreement.


Last update: November 16, 2021