Zero Touch Provisioning for AWS

Prerequisite

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

ZTP using Thingstream portal

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):

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:

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::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\" } } }, \"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":"arn:aws:iam::..."

}

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:

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

Returns the CACertificate 

Returns the DeviceCertificate

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