Zero Touch Provisioning for AWS

Prerequisite

  • You have an account on AWS cloud platform and an instance of AWS IoT Core service

  • Access to:

    1. u-blox Thingstream portal and Security services API interface

    2. module AT command interface.

    3. AWS CLI installed and configured

  • You are familiar with AWS Identity and Access Management (IAM) roles.

  • You can use the AWS SDK.

If not yet done, visit the Tools and Software page and the Getting started guide for items 1 and 2

The following example guides you in the device certificate provisioning procedure and in AWS Just In Time Provisioning configuration.

Procedure overview

This section provides an overview about the required procedure. In the following Example section you will be guided step by step in the implementation.

Once you have an account on the AWS cloud platform, the below procedure can be followed in order to provision a device with necessary certificates/keys to connect to the AWS IoT Core service by using Zero Touch Provisioning (ZTP).

The procedure is slightly different depending if the device(s) have already bootstrapped or not.

Setting up Zero Touch Provisioning (ZTP )

Zero Touch Provisioning (ZTP ) can be enabled using Security Services APIs or Thingstream UI portal.

ZTP using Security Services APIs

  1. Create a CA certificate on the u-blox Security Service by calling API: /ztp/rootca/create. The API returns the CA certificate, which can be locally stored in a file.

  2. Get your AWS IoT registration code (or Proof of Possession verification code) by using the AWS CLI.

  3. Generate the Proof-of-Possession certificate on u-blox Security Service, by calling the API: /ztp/rootca/popcertificate/generate. The API returns the PoP certificate, which can be locally stored in a file.

  4. Use the AWS CLI or the AWS web console to upload the PoP certificate

  5. Enable the ZTP feature on device. You have two options:

    1. Enable it during the device profile configuration, before sealing the device profile in the module and before the module bootstrap. This is the best option since the feature will be activated by all the devices configured with this device profile, You can do it by calling the API /deviceprofile/bootstrapprovisioning/set

    2. If the module is already bootstrapped, call the API /device/provisioning/set . You can always check the feature authorization status by using the API /device/provisioning/get.

ZTP using Thingstream portal

  1. Create a Root certificate by accessing the Thingstream portal > Security services > ZTP Certificate.

  2. Get your AWS IoT registration code (or Proof of Possession verification code) by using the AWS CLI.

  3. Generate the Proof-of-Possession certificate by selecting on the just generated Root CA certificate and then use the wizard clicking on 'Generate PoP Certificate' .

  4. Use the AWS CLI or the AWS web console to upload the PoP certificate

  5. Enable the ZTP feature on device. You have two options:

    1. If the module is not bootstrapped you can configure the Device profile by accessing Security Services > Device profile section of the portal

    2. If the module is already bootstrapped, select the device in the Thing list section, and activate the ZTP in the Feature panel

Setting up the device

At next synchronization of the module with the u-blox Security Service (bootstrap completion or next security heartbeat message), the certificates and keys for AWS connection will be provisioned into the device automatically. In order to get CA certificate, device certificate and device private key, the customer’s application running on the device can use the AT+USECDEVCERT command on the module.

Setting up AWS Just-in -time provisioning (JITP):

  1. Make sure uploaded Root CA has auto-registration enabled and Status is activated.

  2. Attach a template with the Root CA to configure JITP.

  3. You can now connect the provisioned device to AWS using above certificates and can send/receive message by using any external client of choice, e.g., AWS SDK.

Example

(Step1-4) First of all, you need to get a CA certificate from the u-blox Security Service to use for ZTP and register it into the AWS cloud platform. These operations are a prerequisite to the ZTP feature activation on the module, so they must be performed prior to it.

You can call the API at https://ssapi.services.u-blox.com/v1/ztp/rootca/create to ask for a CA certificate and pass a name for the CA certificate (used to identify it in later actions), and the validity time both for the CA certificate and the device (or client). Validity is expressed in days.

Let’s for example create a “test-ca” CA certificate. We’ll send to the above API this content:

{

"CAName": "test-ca",

"CACertificateValidity": 1825,

"DeviceCertificateValidity": 1825

}

And we’ll receive a response like the following:

{

"CAName": "test-ca",

"CACertificateValidity": 1825,

"DeviceCertificateValidity": 1825,

"Certificate": "-----BEGIN CERTIFICATE<...>-----END CERTIFICATE-----",

"CreatedDate": "2020-07-03T09:07:44Z"

}

Save the CA certificate’s contents (here truncated) into a .pem file. If you have used the UI to generate the CA certificate, you can use the predisposed link to download it.

Next step is to create a Proof-of-Possession verification certificate from the u-blox Security Service:

  • generate the AWS IoT registration code associated to your AWS account. If you don’t already have this information, you can get it by using the AWS CLI:

C:> aws iot get-registration-code


{

"registrationCode": "11fe30cf95<...>838a01be8313c"

}

{

"CAName": "test-ca",

"RegistrationCode": "11fe30cf95<...>838a01be8313c"

}

And we’ll get a response like the following:

{

"CAName": "test-ca",

"PoPCertificate": "-----BEGIN CERTIFICATE-----<...>-----END CERTIFICATE-----"

}

Save the PoP verification certificate contents (here truncated) into a .CRT file.

If using the UI, select the CA certificate from the list, click on Generate PoP certificate link, insert the verification code and download the generated certificate.

NOTE: If the response of the PoP verification response contains the '\n'. Remove these '\n' from the response and then save it into the file.

AWS Just-in-time provisioning configuration (JITP):

You need to create an IAM role and policy for JITP:

To create an IAM role, first create assume-role policy document, copy and paste the following in "assume-role.json" :

{

"Version": "2012-10-17",

"Statement": [

{

"Effect": "Allow",

"Principal": {

"Service": "iot.amazonaws.com"

},

"Action": "sts:AssumeRole"

}

]

}

Use the following command to create an IAM role:

C:>aws iam create-role --role-name iot-jitp-role --assume-role-policy-document file://assume-role.json

Output of command should be:

{

"Role": {

"Path": "/",

"RoleName": "iot-jitp-role",

"RoleId": "12344445556677788",

"Arn": "arn:aws:iam::12345678342:role/iot-jitp-role",

"CreateDate": "2021-03-25T07:07:15+00:00",

"AssumeRolePolicyDocument": {

"Version": "2012-10-17",

"Statement": [

{

"Effect": "Allow",

"Principal": {

"Service": "iot.amazonaws.com"

},

"Action": "sts:AssumeRole"

}

]

}

}

}

Copy the ARN value because it is needed in later steps.

Now we have to create policy for this above created role, copy and paste the following into a file "policy.json":

{

"Version": "2012-10-17",

"Statement": [

{

"Effect": "Allow",

"Action": [

"iot:AddThingToThingGroup",

"iot:AttachPolicy",

"iot:AttachPrincipalPolicy",

"iot:AttachThingPrincipal",

"iot:CreateCertificateFromCsr",

"iot:CreatePolicy",

"iot:CreateThing",

"iot:DescribeCertificate",

"iot:DescribeThing",

"iot:DescribeThingGroup",

"iot:DescribeThingType",

"iot:DetachPolicy",

"iot:DetachThingPrincipal",

"iot:GetPolicy",

"iot:ListAttachedPolicies",

"iot:ListPolicyPrincipals",

"iot:ListPrincipalPolicies",

"iot:ListPrincipalThings",

"iot:ListTargetsForPolicy",

"iot:ListThingGroupsForThing",

"iot:ListThingPrincipals",

"iot:RegisterCertificate",

"iot:RegisterThing",

"iot:RemoveThingFromThingGroup",

"iot:UpdateCertificate",

"iot:UpdateThing",

"iot:UpdateThingGroupsForThing",

"iot:AddThingToBillingGroup",

"iot:DescribeBillingGroup",

"iot:RemoveThingFromBillingGroup"

],

"Resource": [

"*"

]

}

]

}

Use the following command to update the policy for the above create role:

C:> aws iam put-role-policy --role-name iot-jitp-role --policy-name IoTJITPPolicy --policy-document file://policy.json

You need to create a template for JITP, for that copy paste the following content into a file "template.json" and update roleArn with your Role ARN created above :

{

"templateBody":"{ \"Parameters\" : { \"AWS::IoT::Certificate::Country\" : { \"Type\" : \"String\" },\"AWS::IoT::Certificate::CommonName\" : { \"Type\" : \"String\" }, \"AWS::IoT::Certificate::Id\" : { \"Type\" : \"String\" } }, \"Resources\" : { \"thing\" : { \"Type\" : \"AWS::IoT::Thing\", \"Properties\" : { \"ThingName\" : {\"Ref\" : \"AWS::IoT::Certificate::CommonName\"}, \"AttributePayload\" : { \"version\" : \"v1\", \"country\" : {\"Ref\" : \"AWS::IoT::Certificate::Country\"}} } }, \"certificate\" : { \"Type\" : \"AWS::IoT::Certificate\", \"Properties\" : { \"CertificateId\": {\"Ref\" : \"AWS::IoT::Certificate::Id\"}, \"Status\" : \"ACTIVE\" } }, \"policy\" : {\"Type\" : \"AWS::IoT::Policy\", \"Properties\" : { \"PolicyDocument\" : \"{\\\"Version\\\": \\\"2012-10-17\\\",\\\"Statement\\\": [{\\\"Effect\\\":\\\"Allow\\\",\\\"Action\\\": [\\\"iot:Connect\\\",\\\"iot:Publish\\\"],\\\"Resource\\\" : [\\\"*\\\"]}]}\" } } } }",

"roleArn":"YOUR-ROLE-ARN"

}

The following step is to upload the root CA certificate and the PoP certificate into AWS IoT, and you can do this by using the following command:

C:> aws iot register-ca-certificate --ca-certificate file://test-ca.pem --verification-cert file://test-pop.pem --set-as-active --allow-auto-registration --registration-config file://template.json

This template set as Thing name in AWS platform, the Common Name of the device certificate, that is the RoTPublicUID. As you remember the RoTPublicUID is the unique and immutable identity of the module. This approach ensures that whenever you need to replace the device certificate, the AWS platform will continue to reference to the same Thing, because even generating a new certificate for that device, the RoTPublicUID (and so the Common Name) will not change.


By visiting the AWS IoT web console, you can now see that an entry appeared in the Certificate Authorities section.

Check if the CA has been properly activated. If not, use the AWS CLI – referencing the certificate id returned by the previous command - to activate it.

C:> aws iot update-ca-certificate --certificate-id " f1b13a1b389c18d<...>0365ebba1" --new-status ACTIVE

Now we can see on the AWS IoT web console that the status of the CA certificate is active:


Connect the device to AWS IoT Core with TLS mutual authentication

AWS IoT requires mutual authentication to establish a TLS connection. Therefore the device, to verify the identity of the server, needs the AWS Certificate pre-installed; you can download it using this link. This certificate shall be pre-installed in the production line and it is same for all the devices.

To setup the TLS session, you need to get device private key, certificate and Root CA from the module. You can use the following AT commands for that purpose:

  1. Check if the device certificate has been provisioned using: AT+USECDEVCERT?

returns +USECDEVCERT: 0,0,0 if PrivateKey, DeviceCertificate and CaCertificate are present in module

  1. Get CA Certificate: AT+USECDEVCERT=2

Returns the CACertificate

  1. Get Device Certificate: AT+USECDEVCERT=1

Returns the DeviceCertificate

  1. Get Private Key: AT+USECDEVCERT=0

Returns the PrivateKey

Note: The very first time when the device connects, it needs to present full certificate chain (Device certificate and Root CA certificate used to sign the device certificate). Full certificate chain means that the device certificate and Root CA is presented as a single certificate. This can be achieved by appending Root CA below device certificate. For subsequent connection, full certificate chain is not required only device certificate is enough.

You can find further information in the AWS Just In Time Provisioning blog.

To avoid exposing the private key and the certificate, we suggest to use the Local Chip-to-chip Security that protects the communication between the modem and the MCU.

You can now connect to AWS IoT using above certificates and start communicating by using any external client of choice e.g. AWS SDK.

Refer to AWS website to find some tutorials on how to connect the device using MQTT or HTTPS protocols