Instant registration of Amazon IoT device certificates using Amazon Lambda

Posted by jmarcv on Sun, 26 Dec 2021 13:55:07 +0100

Background introduction

In order to ensure the security of communication, the certificate based TLS 1.2 two-way authentication system is used for MQTT communication between Amazon IoT equipment and Amazon IoT Core. The so-called two-way authentication means that Amazon IoT device end needs to install Amazon IoT device certificate, and the CA certificate used to issue the certificate needs to be granted credit by Amazon IoT Core, so as to complete Amazon IoT device end authentication by Amazon IoT Core. In addition, Amazon IoT devices will also verify the identity of Amazon IoT Core.

In order to ensure the two-way secure connection between Amazon IoT devices and Amazon IoT Core, two types of certificates need to be installed on the Amazon IoT device side:

  1. Amazon IoT device certificate
  2. CA certificate for Amazon IoT platform

When to use instant enrollment for device certificates

When users want to use the CA certificate purchased or self issued from a third party organization and connect the device with the device certificate issued by the CA certificate to Amazon IoT Core, they can use the instant registration function. If you want to directly use the device certificate issued by Amazon IoT CA certificate to register and activate the device, you can refer to the Amazon Certificate Vending Machine scheme.

The implementation steps are as follows:

  1. Create a CA certificate and register and activate it on Amazon IoT Core.
  2. Use this CA certificate to issue a device certificate and install it on Amazon IoT devices.
  3. Create Amazon Lambda function to realize automatic registration of device certificate on Amazon IoT Core.
  4. The first connection between Amazon IoT devices and Amazon IoT Core.

preparation

The Amazon IoT device in this article will use an Amazon Linux EC2 instance to simulate and use the MQTT Mosquitto Client tool to simulate the MQTT message interaction process. Amazon IoT devices in practical applications need to integrate Amazon IoT SDK to realize interaction with Amazon IoT Core. In addition, all the next operations take Amazon cloud Technology Beijing as an example.

Amazon AWSCLI, the command-line tool of Amazon cloud technology, is installed on Amazon Linux EC2 instance by default. If readers use other instances or their own computers, please refer to this link to install Amazon AWSCLI.

Step 1: create a CA certificate and register and activate it on Amazon IoT Core

In a real scenario, a user's device certificate is often issued by an intermediate CA certificate rather than a root CA certificate. For convenience, this step will skip the intermediate CA certificate and directly issue the device certificate with the root certificate. And because the actual purchase of CA certificate will make the author pay N months' salary, here we will use OpenSSL to issue the certificate. Users can choose different issuance methods according to their actual situation.

Log in to Amazon EC2 instance and execute the following command to create private key and corresponding CA certificate:

$ mkdir cert
$ cd cert
$ openssl genrsa -out CA_Private.key 2048
$ openssl req -x509 -new -nodes -key CA_Private.key -sha256 -days 365 -out CA_Certificate.pem

Slide left and right to see more

We need to register this CA certificate with Amazon IOT Core. For security, Amazon IOT Core provides a corresponding audit process to ensure that you hold both the CA certificate and the corresponding private key. Therefore, before finally registering the CA certificate, We also need to generate an intermediate certificate for verifying the identity of the CA certificate and the private key holder according to the process (please note that this certificate is not the CA certificate created above). The following Amazon AWSCLI command will return a randomly generated authentication code, which will be bound to your account. Record this authentication code and we will use it soon.

$ aws iot get-registration-code

Use OpenSSL again to generate the private key and certificate request file for authentication (Amazon CSR – Amazon Certificate Signing Request).

$ openssl genrsa -out Verification_Private.key 2048
$ openssl req -new -key Verification_Private.key -out Verification.csr

Slide left and right to see more

In the process of creating Amazon CSR, you will be prompted to enter the following contents and fill the authentication code recorded in the previous step into Common Name:

...Organization Name (eg, company) []:Organizational Unit Name (eg, section)Common Name (e.g. server FQDN or YOUR name) []: XXXXXREGISTRATIONCODEXXXXX...

Next, use the CA certificate and private key, and the Amazon CSR created above to generate an intermediate certificate for authentication.

$ openssl x509 -req -in Verification.csr -CA CA_Certificate.pem -CAkey 
CA_Private.key -CAcreateserial -out Verification.crt -days 365 -sha256

Slide left and right to see more

Finally, import the CA certificate and intermediate certificate through the following command, and Amazon IoT Core will complete the registration and activation of the CA certificate. At the same time, enable the automatic registration of device certificates when the device is connected to Amazon IoT Core by setting – allow auto registration. The output of this command will return the ID(caCertificateId) of the corresponding CA certificate on Amazon IoT Core.

$ aws iot register-ca-certificate --ca-certificate
file://CA_Certificate.pem --verification-certificate 
file://Verification.crt --set-as-active --allow-auto-registration

Slide left and right to see more

Step 2: use CA certificate to issue equipment certificate

After we have created and registered the CA certificate, we can start issuing the equipment certificate with this CA certificate. The steps are as follows:

Create a private key for the device certificate Key and the corresponding certificate request file Device_Certificate.csr.

$ openssl genrsa -out Device.key 2048
$ openssl req -new -key Device.key -out Device_Certificate.csr

Slide left and right to see more

Use CA certificate, CA certificate private key and certificate request file to issue device certificate Device_Certificate.crt.

$ openssl x509 -req -in Device_Certificate.csr -CA CA_Certificate.pem -CAkey 
CA_Private.key -CAcreateserial -out Device_Certificate.crt -days 365 -sha256

Slide left and right to see more

After creating the device certificate and installing it on the device, you may ask, how do I register and use the device certificate? Of course, you can complete the registration on Amazon IoT Core through Amazon AWSCLI command line or even graphical interface, but in the face of thousands of Amazon IoT devices, no one should want to do it manually. Next, we will introduce how to use Amazon Lambda function to automatically complete the registration process of device certificate when the device connects to Amazon IoT Core for the first time.

Step 3: create Amazon Lambda function and Amazon IoT rules to activate and attach the device certificate on Amazon IoT Core

When an Amazon IoT device connects to the Amazon IoT Core for the first time, if its integrated device certificate is issued by a CA certificate registered on the Core, the corresponding device certificate will be automatically registered. The default state after registration is "PENDING_ACTIVATION", which means that although the device certificate has been successfully registered, it is still in the state of waiting to be activated. Meanwhile, this connection action will send a message to MQTT Topic "$aws/events/certificates/registered /" of Amazon IoT Core by default. The message event will be in the following format:

{

"certificateId": "<certificateID>",

"caCertificateId": "<caCertificateId>",

"timestamp": "<timestamp>",

"certificateStatus": "PENDING_ACTIVATION",

"awsAccountId": "<awsAccountId>",

"certificateRegistrationTimestamp": "<certificateRegistrationTimestamp>"

}

Slide left and right to see more

As we all know, the execution of Amazon Lambda function can be triggered by events. Next, we will do two things:

  1. Create an Amazon Lambda function to receive incoming events, execute code logic to activate the device certificate and attach a Policy to give the device corresponding permissions.
  2. Create an Amazon IoT rule, subscribe to the MQTT Topic "$aws/events/certificates/registered /", and when a message is sent to this Topic, forward the message to the Amazon Lambda function for processing (activate the certificate and attach the Policy).

First, let's create this Amazon Lambda function:

  1. Log in to Amazon Console and enter Amazon Lambda page.

  1. Click "create function" and select "create from scratch".
  2. Fill in "name", select "Node.js 6.10" for running language, and select "create custom role" for role.

  1. In the new pop-up window, select "create new Amazon IAM role" for Amazon IAM role, fill in the role name, click "view policy document" and click "Edit".

  1. Click "Edit" to pop up a window, prompting that you must read the relevant documents before editing. Here, we directly click the OK button. Of course, if you have time, it is recommended to read the document first.
  2. Replace the existing Policy with the following Policy. You can see here that we have added the permission to update the certificate and attach Policy to Amazon Lambda function. Click allow to complete the configuration of roles and policies.
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws-cn:logs:*:*:*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "iot:UpdateCertificate",
        "iot:CreatePolicy",
        "iot:AttachPrincipalPolicy"
      ],
      "Resource": "*"
    }
  ]
}

Slide left and right to see more

7. Click Create function to enter the function configuration interface. The current code of the replacement function is:

/** 
This node.js Lambda function code creates and attaches an IoT policy to the 
just-in-time registered certificate. It also activates the certificate. The Lambda
function is attached as a rule engine action to the registration topic 
$aws/events/certificates/registered/<caCertificateID>
**/

var AWS = require('aws-sdk');

exports.handler = function (event, context, callback) {

  //It is also written in the certificateARN according to the actual deployment area.
  var region = "cn-north-1";
  var accountId = event.awsAccountId.toString().trim();
  var iot = new AWS.Iot({
    'region': region,
    apiVersion: '2015-05-28'
  });

  var certificateId = event.certificateId.toString().trim();

  //Here you can replace it with the topic name you want
  var topicName = `JITR/test`;
  var certificateARN = `arn:aws-cn:iot:${region}:${accountId}:cert/${certificateId}`;
  var policyName = `Policy_${certificateId}`;
  //Define policies and grant permissions to allow IoT devices to connect, publish, subscribe and accept messages
  var policy = {
    "Version": "2012-10-17",
    "Statement": [
      {
        "Action": [
          "iot:Publish",
          "iot:Subscribe",
          "iot:Connect",
          "iot:Receive"
        ],
        "Effect": "Allow",
        "Resource": [
          "*"
        ]
      }
    ]
  };

  /*
  Create Policy
  */
  iot.createPolicy({

    policyDocument: JSON.stringify(policy),
    policyName: policyName
  }, (err, data) => {

    //Ignore if the policy already exists
    if (err && (!err.code || err.code !== 'ResourceAlreadyExistsException')) {
      console.log(err);
      callback(err, data);
      return;
    }
    console.log(data);
    /*
    Attach Policy to device certificate
    */
    iot.attachPrincipalPolicy({

      policyName: policyName,
      principal: certificateARN
    }, (err, data) => {

      //Ignore if the policy is already attached
      if (err && (!err.code || err.code !== 'ResourceAlreadyExistsException')) {
        console.log(err);
        callback(err, data);
        return;
      }
      console.log(data);
      /*
      Activate certificate
      */
      iot.updateCertificate({
        certificateId: certificateId,
        newStatus: 'ACTIVE'
      }, (err, data) => {
        if (err) {
          console.log(err, err.stack);
          callback(err, data);
        } else {
          console.log(data);
          callback(null, "Success, created, attached policy and activated the certificate " + certificateId);
        }
      });
    });
  });
}

Slide left and right to see more

8. Click "save" in the upper right corner of the page to complete the creation of Amazon Lambda function.

After the Amazon Lambda function is created, we continue to create Amazon IoT rules:

  1. Enter Amazon IoT interface.
  2. Click "action" on the left side of the page, and then click "create" in the upper right corner.

  1. Fill in the "name" and "description" of the rule on the create rule page, and fill in an asterisk "*" in the "attribute" column.

  1. Fill in "$aws/events/certificates/registered /" in the "subject filter criteria" in the create rule page. Note that the ID of the CA certificate previously issued with OpenSSL should be replaced. This ID can be obtained by clicking "security" - > "CA" on the left side of Amazon IoT interface.

  1. Click "add operation" in setting one or more operations, select "call Amazon Lambda function to transfer message data", and then click "configure operation".

  1. Function nameselect the name of the Amazon Lambda function you created earlier, and then click Add action.

7. Click "create rule" to complete the configuration of Amazon IoT rules.

So far, the Amazon Lambda function and Amazon IoT rule are created. Next, let's try to connect the device to Amazon IoT Core.

Step 4: the first connection between Amazon IoT device and Amazon IoT Core

In order to simulate a device, you can install the Amazon IoT SDK and call Amazon cloud technology through your own code to realize all functions. Here, in order to simplify the steps and save time, we choose to directly install the MQTT Mosquitto Client tool on Amazon EC2 created earlier.

Log in to Amazon EC2 instance and execute the following command:

$ sudo wget http://download.opensuse.org/repositories/home:/oojah:/mqtt/CentOS_CentOS-7/home:oojah:mqtt.repo -O /etc/yum.repos.d/mqtt.repo

$ sudo yum install mosquitto mosquitto-clients -y

#If the execution of the above command depends on the missing error, you can add -- skip broken and execute it again
$ sudo yum install mosquitto mosquitto-clients -y --skip-broken

Slide left and right to see more

Go to the cert directory you created earlier.

$ cd cert

Merge CA certificate and device certificate into a new certificate to form a valid certificate chain.

$ cat Device_Certificate.crt CA_Certificate.pem > Device_CA_Certificate.crt

Slide left and right to see more

Execute mosquitto_ The pub command publishes a message to the corresponding topic, which is also the first connection between the device and Amazon IoT Core. If you recall the previous steps, so far our device certificate only exists on the device and has not been registered on Amazon IoT Core, then the next time to witness a miracle is coming!

$ mosquitto_pub --cafile root-CA.crt --cert Device_CA_Certificate.crt --key Device.key -h xxxxxxxxxxxxxx.iot.cn-north-1.amazonaws.com.cn -p 8883 -q 1 -t JITR/test -i anyclientID --tls-version tlsv1.2 -m "Hello" -d

Slide left and right to see more

  • The - cafile in the command is the CA certificate of Amazon IoT Core, which is used by the device to verify the identity of Amazon IoT Core. This file can be obtained through this link
  • - cert in the command is the certificate chain after merging CA certificate and device certificate
  • - key in the command is the private key of the device
  • - h in the command is the access point of Amazon IoT Core, which can be obtained by clicking "Settings" in the lower left corner of Amazon IoT interface
  • - t in the command is the topic you want to publish the message to. Here I publish it to JITR/test. You can choose the topic you want to publish
  • The - i in the command can be named as you want

After executing this command for the first time, you will see the following error messages. Why?

Client anyclientID sending CONNECT
Error: The connection was lost.

In fact, when the device connects to Amazon IoT Core for the first time, the device certificate has not been registered, so TLS authentication will fail. This connection action will publish a registration message to "$aws/events/certificates/registered /". After receiving this message, Amazon Lambda function will complete the registration of device certificate and attach Policy. Then we can execute this command again.

$ mosquitto_pub --cafile root-CA.crt --cert Device_CA_Certificate.crt --key Device.key -h xxxxxxxxxxxxxx.iot.cn-north-1.amazonaws.com.cn -p 8883 -q 1 -t JITR/test -i anyclientID --tls-version tlsv1.2 -m "Hello" -d

Slide left and right to see more

The output is as follows:

Client anyclientID sending CONNECT
Client anyclientID received CONNACK
Client anyclientID sending PUBLISH (d0, q1, r0, m1, 'JITR/test', ... (5 bytes))
Client anyclientID received PUBACK (Mid: 1)
Client anyclientID sending DISCONNECT

Slide left and right to see more

It should be noted here that in the actual environment, the user's code logic is responsible for handling this process, that is, after the first connection failure, it is necessary to automatically reconnect one or more times to complete the certificate registration and device activation.

At this time, enter the Amazon IoT interface, click Security on the left, and you can see that our device certificate has been registered and activated in the certificate page.

Reference link

Author of this article


Guo song
Amazon cloud technology solution architect
Responsible for architecture consulting and design optimization of enterprise customers, and committed to the application and promotion of Amazon IoT and storage services in domestic and global enterprise customers. Before joining Amazon cloud technology, he worked as a system engineer in EMC R & D center and had in-depth research on high availability architecture, scheme and performance tuning of enterprise storage applications.

Topics: IoT