DEV Community

Wesley Wong
Wesley Wong

Posted on

AWS IoT: Step by step guide on fleet provisioning with CSR using ESP32-S3

1. Introduction: Fleet provisioning with CSR

Fleet provisioning is a secure method where an IoT device generates its own private key locally and sends a CSR to AWS to obtain a uniquely signed X.509 client certificate upon its first connection.

How it works:

  • Local Key Generation: The device creates its own private key and a CSR on the device itself. The private key never leaves the device.
  • Initial Connection: The device connects to AWS IoT Core using a temporary mechanism (such as a provisioning claim certificate). Signing Request: The device sends an MQTT request containing the CSR via the CreateCertificateFromCsr API.
  • Certificate Issuance: AWS IoT Core signs the CSR—either using an AWS-managed CA or a self-managed certificate provider linked to an external PKI or AWS Private CA—and returns the signed certificate
  • Registration & Activation: Using a provisioning template, AWS IoT registers the "Thing," attaches security policies, and activates the certificate for normal operations.

Key Benefits

  • Enhanced Security: The private key is generated on the device and is never transmitted over the network or exposed during manufacturing. It is also ideal for hardware that uses a secure element where private keys cannot be imported.
  • Custom Certificate Authorities: Enables self-managed signing so you can use your own Public Key Infrastructure (PKI) or custom validity periods and algorithms instead of relying solely on AWS-managed certificates.

Fleet provisioning flow


2. Fleet provisioning with CSR using ESP32-S3

2.1 My Setup

  • Ubuntu 26.04 LTS
  • ESP32-S3-WROOM-1-N16R8
  • esp-idf v5.5.5
    • Please refer to the installation guide provided at this Link
  • esp-aws-iot 202406.05-LTS-release
    • git clone -b "202406.05-LTS-release" --recursive https://github.com/espressif/esp-aws-iot
  • The folder structure of this demo would be:
esp/
├── esp-aws-iot/
│   └── examples/
│       └── fleet_provisioning/
│           └── fleet_provisioning_with_csr/
│
└── esp-idf/
Enter fullscreen mode Exit fullscreen mode

2.2 Build the example
Execute the following commands sequentially to verify that the setup is properly configured.

cd esp/esp-idf
. ./export.sh
cd
cd esp/esp-aws-iot/examples/fleet_provisioning/fleet_provisioning_with_csr
idf.py set-target esp32s3
idf.py build
Enter fullscreen mode Exit fullscreen mode

2.3 Create the provision policy
An AWS provisioning policy defines the permissions and rules used to automate, control, and secure the creation of cloud resources, accounts, or connected devices.

  • In AWS IoT panel, navigate to Security > Policies > Create policy

AwsIot_Create_Policy

  • Enter a policy name (e.g., FleetProvTestPolicy), and then select 'JSON' from the policy statements options.

AwsIot_Edit_Policy

  • Paste below JSON content into the policy document. [aws-region], [aws-account-id] and [template-name] should be changed according to your setup. For example:
    • arn:aws:iot:eu-west-1:123456789012:topic/$aws/provisioning-templates/FleetProvTestTemplate/provision/*
{
   "Version": "2012-10-17",
   "Statement": [
     {
       "Effect": "Allow",
       "Action": [
         "iot:Connect"
       ],
       "Resource": "*"
     },
     {
       "Effect": "Allow",
       "Action": [
         "iot:Publish",
         "iot:Receive"
       ],
       "Resource": [
         "arn:aws:iot:[aws-region]:[aws-account-id]:topic/$aws/certificates/create-from-csr/*",
         "arn:aws:iot:[aws-region]:[aws-account-id]:topic/$aws/provisioning-templates/[template-name]/provision/*"
       ]
     },
     {
       "Effect": "Allow",
       "Action": "iot:Subscribe",
       "Resource": [
         "arn:aws:iot:[aws-region]:[aws-account-id]:topicfilter/$aws/certificates/create-from-csr/*",
         "arn:aws:iot:[aws-region]:[aws-account-id]:topicfilter/$aws/provisioning-templates/[template-name]/provision/*"
       ]
     }
   ]
 }
Enter fullscreen mode Exit fullscreen mode

2.4 Create claim certificate
A claim certificate in AWS IoT Core Fleet Provisioning is a shared, bootstrap X.509 certificate and private key pre-installed on devices during manufacturing to let them connect to AWS IoT for the first time.

  • In AWS IoT Core, navigate to Security > Certificates > Add certificate > Create certificate
  • Select "Auto-generate new certificate (recommended)" and set the status to "Active". Click "Create".
  • Click "Download all".
  • Copy downloaded private key and cert content into "claim_private.key" and "claim_cert.crt" in folder "fleet_provisioning_with_csr/spiffs_image/certs"
  • Select the certificate you created. Click "Attach policies", choose your provisioning policy (FleetProvTestPolicy), and click "Attach policy"

AwsIot_Attach_Policy


2.5 Create IAM role for fleet provisioning
An IAM role in AWS IoT Fleet Provisioning is needed because the AWS IoT service itself needs permission to create, configure, and register resources (like Things, certificates, and policies) on your behalf inside your AWS account.

  • In IAM dashboard, navigate to Access Management > Roles. Click "Create role"
  • Select "AWS service" in trust entity type.
  • Select "IoT" in use case

AwsIot_Create_IAM_Role

  • Click "Next" > "Next"
  • Name the role. e.g: FleetProvRole and then click "create role"

2.6 Create thing policy
A thing policy is needed because device thing would be created during fleet provisioning. It would be attached thing policy. Please refer to section 2.3 on how to create policy. You could use your own thing policy or copy below general policy.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iot:Subscribe",
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": "iot:Connect",
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": "iot:Receive",
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": "iot:Publish",
      "Resource": "*"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

2.7 Create provisioning template
A provisioning template is a JSON document that uses parameters to describe the resources your device must use to interact with AWS IoT. A provisioning template contains two sections: Parameters and Resources. There are two types of provisioning templates in AWS IoT. One is used for just-in-time provisioning (JITP) and bulk registration, and the second is used for fleet provisioning.

  • In AWS IoT core, navigate to Connect > Connect to many devices > Provisioning templates
  • Click "Create provisioning template"
  • Select "Provisioning devices with claim certificates" and the click "Next"
  • Follow pictures below to configure the template
    • Select "Active" in Provisioning template status.
    • Select the IAM role created in section 2.5 in Provisioning role.
    • Select the fleet provisioning policy created in section 2.3 in Claim certificate policy.
    • Check the certificate created in section 2.4 in Claim certificates.
    • Click "Next"

AwsIot_Create_PT1

AwsIot_Create_PT2

  • Select "Don't use a pre-provisioning action", enable "Automatically create a thing resource when provisioning a device" and then click "Next"

AwsIot_Create_PT3

  • Check the thing policy created in section 2.6 and then click "Next"

AwsIot_Create_PT4

  • Check the details and then click "Create template"

2.8 Config demo example program
2.8.1 Wifi router setup

  • Enter your router setting (SSID and password) in menuconfig > Example Connection Configuration

ESP32_Config_Wifi

2.8.2 AWS setup

  • In AWS IoT core > Domain configurations, you could find the domain name.

ESP32_Config_Aws1

  • Navigate to AWS setup by menuconnfig > Example configuration.
  • Copy and paste the domain name into "Endpoint of the MQTT broker to connect to".
  • Paste the template name created in section 2.7 into "Name of the provisioning template".
  • Set the device serial number, e.g: FleetProvTestThing. This would be the name of thing created during fleet provisioning.

ESP32_Config_Aws2


2.9 Build, flash and run demo example
After successful fleet provisioning, "FleetProvTestThing" thing should be created in AWS IoT core.

Result1

Result2


3. Demo source code

awsiot_fleet_provisioning_with_csr

Top comments (0)