The Internet of Things on AWS – Official Blog

Provisioning with a bootstrap certificate in AWS IoT Core

One of the core tenets of managing IoT devices is provisioning, which is the process of registering a device on a particular platform or a system. When bootstrapping your devices, it’s important to establish mutual authentication between the device and an Internet of Things (IoT) endpoint to prevent threats like man-in-the-middle attacks. Device certificates are by far the most secure means of authentication, and generally the first choice for device identity.

In this post, we do a deep dive into how AWS IoT Core and AWS IoT Device Management help you quickly provision devices with a bootstrap certificate. AWS IoT Core is a managed cloud service that lets connected devices easily and securely interact with cloud applications and other devices. AWS IoT Device Management makes it easy to securely onboard, organize, monitor, and remotely manage IoT devices at scale.

What is a bootstrap certificate, and why do you need one?
Consider the use case of a fictional company ‘SmartTeeth’ that makes a line of WiFi-connected toothbrushes. They contract out the manufacturing of these toothbrushes to a third party who is responsible for placing device certificates on the toothbrush for connection to the cloud. However, SmartTeeth wants to limit what cloud activities are allowed by the toothbrush until it’s in the hands of the customer.

Ideally, these initial device certificates would only allow the toothbrush to connect to the cloud to register itself and request its fully functional certificates. It would also be ideal if this activity was automated and transparent to SmartTeeth’s customers. When the toothbrush connects for the first time, all necessary resources in the cloud are created to facilitate the replacement of the initial certificate with an operational one.

The following diagram shows the process of replacing the initial credentials with the final credentials after purchase.

 

In the diagram, a SmartTeeth customer decides to install a bootstrap certificate, which is a low-privilege unique certificate that is associated with each device during the manufacturing process. This certificate has an AWS IoT policy associated with it to restrict devices to only allow connecting to AWS IoT Core and accessing specific MQTT topics to fetch the final certificate.

Device provisioning workflow
The process of device provisioning using a bootstrap certificate consists of three steps:

  1. Device assembly
  2. Device registration
  3. Device activation

Device assembly
Device assembly happens during the manufacturing process, where the supplier burns the certificate onto the device. During this process, devices are manufactured with unique bootstrap certificates.

When implementing this approach, the following conditions should be met:

  • A CA certificate is registered with AWS IoT Core and auto-registration is enabled.
  • A device is manufactured with a device certificate created with the registered CA certificate.

Device registration
Device registration is the process of registering a device as a thing within AWS IoT Core. During this process, you must do the following:

  • Register the thing and the bootstrap certificate.
  • Create and attach policies to the bootstrap certificate.
  • Associate the bootstrap certificate with the thing.
  • Provision the final certificate within AWS IoT Core (marked as inactive).
  • Add the thing to an AWS IoT thing group or type.

However, before you do these steps, there is one crucial step: The device supplier must provide an allowed list of devices (also called a whitelist). This file can be just a list of device IDs, or can include other attributes as well:

cat ./allowed-device-list.txt
demo001
demo002
demo003

During the device registration process, check the allow list file to validate whether the device has been fully vetted by the supplier. Ensure that it has the bootstrap certificate signed by a customer-specific CA.

There are multiple ways to initiate the device registration process. In this use case, you use the just-in-time registration (JITR) feature of AWS IoT Core.

To use the JITR process for device registration, make sure of the following:

  • The device has its desired device ID embedded as the Common Name in its device certificate.
  • The device allow list file is stored in an AWS service, such as Amazon S3.

This is how the JITR process for device registration works:

  1. The device (thing) connects to AWS IoT Core using MQTT with the bootstrap certificate.
  2. Using JITR, AWS IoT Core detects an unregistered certificate that is signed with a registered CA. It automatically registers it (setting its status to pending_activation) and disconnects the device.
  3. Upon disconnection, the Certificate Activator AWS Lambda function is triggered, which verifies the allow list.
  4. If verification is successful, the Lambda function activates the certificate. It also initiates a device-provisioning workflow that includes associating the certificate and policies, creating the final certificate, and creating the thing group or type.

Device activation
Device activation occurs when the device is powered on for the first time and connects to the AWS IoT Core endpoint using the bootstrap certificate. The connection downloads the device’s final certificate with full privileges. The overall architecture and flow are:

  1. The device connects to AWS IoT Core using a bootstrap certificate and is sent a certificate rotation job.
  2. The device sends a “get certificate” message.
  3. The CertificateRotation Lambda function responds to the device with a pre-signed URL of an operational certificate.
  4. The device fetches the operational certificate from the S3 bucket.
  5. The device rotates the certificate and reconnects to the AWS IoT endpoint.

The following diagram shows these steps.

 

Adhering to the best practice of granting the least possible privileges, the bootstrap certificate only has sufficient privileges to complete the flow described earlier. This includes:

  • Connecting to AWS IoT Core using its device ID as the MQTT client ID.
  • Subscribing to the device’s specific AWS IoT Job topics.
  • Publishing and subscribing to the MQTT topics required to rotate certificates.

One important feature of AWS IoT Device Management used here is the continuous jobs feature. As a one-time initial setup event, a continuous job for rotating certificates is created and can target an AWS IoT thing group. During the device registration process, new registered devices are added to this thing group, which automatically queues up a job for them to rotate certificates upon first connection.

When the device connects to the AWS IoT Core endpoint, it subscribes to the AWS IoT job topics $aws/things/{thingName}/jobs/notify-next and $aws/things/{thingName}/jobs/get/+.

The job document returned by AWS IoT jobs contains the publish and subscribe topics for certificate rotation.  An example job document is as follows:

{
  "get": {
    "subscribe": "certificates/{thingName}/get/+",
    "publish": "certificates/{thingName}/get"
  },
  "ack": {
    "subscribe": "certificates/{thingName}/ack/+",
    "publish": "certificates/{thingName}/ack"
  }
}

The device subscribes to the get.subscribe topic (certificates/{thingName}/get/+) identified in the job document, followed by publishing an empty message to the get.publish (certificates/{thingName}/get) topic.

AWS IoT Core routes the message to the CertificateRotation Lambda function. It uses an AWS IoT rule action that monitors the MQTT topic certificates/+/get and routes all messages received on it to the function.  The following is an example message sent from AWS IoT Core to the function (post message transformation by the AWS IoT rule):

{
  "deviceId": "device123",
  "action": "get"
}

Upon receiving the request, the CertificateRotation Lambda function validates that the device is on the allow list; if so, then it:

  1. Downloads the S3 object metadata associated with the certificate package to retrieve the certificateId.
  2. Activates the certificate.
  3. Constructs and returns a pre-signed URL to the device to download the certificate package.

Finally, the device status is updated to activated.

The following is an example of a successful response sent from certificate-vendor to the device, published to the certificates/{thingName}/get/accepted MQTT topic:

{
  "location": "https://certificatevendor-us-west-2.s3.amazonaws.com/certificates/device123.zip?AWSAccessKeyId=xxxxxxx&Expires=1542129538&Signature=xxxxx"
}

If any failures occur during this flow, a rejected message is sent to the device and published to the certificates/{thingName}/get/rejected MQTT topic. Here is an example:

{
  "message": "DEVICE_NOT_WHITELISTED"
}

After the updated certificate is in place, the device subscribes to the ack.subscribe topic (certificates/{thingName}/ack/+). Then, it publishes an empty message to the ack.subscribe (certificates/{thingName}/ack) topic to inform the CertificateRotation function of its success. The function subscribes to these success notifications and removes the device from the registered devices group.

At this point, the device has successfully retrieved and applied its new operational certificate. This certificate has been associated with a more open operational policy, allowing the device to interact with the cloud as designed.

Security best practices
The device requests (over MQTT) a pre-signed URL for the secure download of the final certificates for the device. A device-specific profile is created and associated with the device’s bootstrap certificate to force the device to use its thing name as the MQTT clientId. This ensures that the device can only receive final certificates intended for itself.

A second general profile is associated with the bootstrap certificate to allow the receipt of AWS IoT jobs. It also allows for both making publishing requests to and receiving responses from the CertificateVendor Lambda function as itself. Only devices on the allow list are authorized to request new certificates.

Another security best practice is to send an explicit activation API request to initiate certificate rotation. This provides a safeguard to prevent non-approved devices (for example, stolen devices or devices installed by non-approved third parties) from self-elevating their privileges.

Finally, as a supplement or alternative to maintaining an allow list of devices, you can use a blacklist of certificates known as a certificate revocation list (CRL). In this case, the CertificateActivation Lambda function checks the CRL (stored in Amazon S3) before allowing the certificate to be activated.

Conclusion
In this blog post, we walked through one of the methodologies of device provisioning where customers can limit the device privileges during the manufacturing process until it reaches the end customer. Several important architectural decision points were made in this provisioning flow:

  • Using serverless computing (API Gateway, Lambda) to build the microservices. Provisioning is usually a one-time process and is non-continuous over a device lifecycle. You don’t have to run servers (Amazon EC2) or containers (Amazon ECS or Amazon EKS) to keep from incurring costs.
  • Using JITR to automate global provisioning.
  • Using AWS IoT jobs as a trigger for retrieval of the final certificate instead of hardcoding this into the device’s startup routine. This way, in case of a security breach, this functionality can also be reused to renew certificates or rotate certificates. You can use AWS IoT Device Defender to track certificate renewal or security breaches and kick off a certificate rotation job.