By using AWS re:Post, you agree to the AWS re:Post Terms of Use

How can I use JITP with AWS IoT Core?

10 minute read
0

I want to set up a just-in-time provisioning (JITP) environment that has a custom root certificate authority (CA) registered with AWS IoT Core.

Short description

To set up a JITP environment with AWS IoT Core, first register your CA certificate with AWS IoT Core. Then, attach a provisioning template to your CA.

Resolution

Note: If you receive errors when you run AWS Command Line Interface (AWS CLI) commands, then see Troubleshooting errors for the AWS CLI. Also, make sure that you're using the most recent AWS CLI version.

Create a self-signed root CA and verification certificate

Prerequisite:

Install OpenSSL.

To create a self-signed root CA and verification certificate, do the following:

  1. Create a device root CA private key and run the following OpenSSL command:

    $ openssl genrsa -out deviceRootCA.key 2048
  2. Open the VIM text editor, and then create a custom OpenSSL.conf file. For more information on the VIM text editor, see Tutorial on the Vim Tips Wiki website.

  3. To create a custom OpenSSL.conf file, run the following VIM command:

    $ vi deviceRootCA_openssl.conf
  4. To edit the .conf file, press i on the keyboard. Then, copy and paste the following into the file:

    [ req ]
    distinguished_name       = req_distinguished_name
    extensions               = v3_ca
    req_extensions           = v3_ca
    
    [ v3_ca ]
    basicConstraints         = CA:TRUE
    
    [ req_distinguished_name ]
    countryName              = Country Name (2 letter code)
    countryName_default      = IN
    countryName_min          = 2
    countryName_max          = 2
    organizationName         = Organization Name (e.g., company)
    organizationName_default = AMZ
  5. To save the .conf file, press Esc on the keyboard, and then press :wq! on the keyboard. To exit the file, press Enter.

  6. To confirm that the OpenSSL.conf file was created, run the following Linux command:

    $ cat deviceRootCA_openssl.conf
  7. Create a device root CA certificate signing request (CSR). Run the following OpenSSL command:

    $ openssl req -new -sha256 -key deviceRootCA.key -nodes -out deviceRootCA.csr -config deviceRootCA_openssl.conf
  8. Create a device root CA certificate. Run the following OpenSSL command:

    $ openssl x509 -req -days 3650 -extfile deviceRootCA_openssl.conf -extensions v3_ca -in deviceRootCA.csr -signkey deviceRootCA.key -out deviceRootCA.pem
  9. Retrieve the registration code for the AWS Region where you want to use JITP. Then, run the following AWS CLI command:

    $ aws iot get-registration-code --region us-east-2

    Note: Replace us-east-2 with the Region where you want to use JITP.

  10. Create a verification key. Run the following OpenSSL command:

    $ openssl genrsa -out verificationCert.key 2048
  11. Create a verification certificate CSR. Run the following OpenSSL command:

    $ openssl req -new -key verificationCert.key -out verificationCert.csr

    Then, enter the Registration Code in the Common Name field. For example: Common Name (server FQDN or YOUR name) []: xxxxxxxx8a33da.

    Leave the other fields blank.

  12. Create the verification certificate. Run the following OpenSSL command:

    $ openssl x509 -req -in verificationCert.csr -CA deviceRootCA.pem -CAkey deviceRootCA.key -CAcreateserial -out verificationCert.crt -days 500 -sha256

    Important: The registration code of your root CA's Region is required when AWS IoT Core certifies the verification certificate.

    For more information, see Just-in-time provisioning.

Create a JITP template

  1. Create an AWS Identity and Access Management (IAM) role for your AWS IoT Core service. Name it JITPRole. For instructions, see Create a logging role.

    Important: In the following JITP template, you must include the IAM role's Amazon Resource Name (ARN).

  2. Use the VIM text editor to create a JITP template JSON file. Complete the following steps:

  3. Create a JITP template JSON file. Run the following VIM command:

    $ vi jitp_template.json

    Note: Make sure that you save the template with the file name jitp_template.json.

  4. To edit the JITP template, press i on the keyboard. Then, copy and paste the following JITP template into the file:

    {
     "templateBody":"{ \"Parameters\" : { \"AWS::IoT::Certificate::CommonName\" : { \"Type\" : \"String\" },\"AWS::IoT::Certificate::Country\" : { \"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\\\" ], \\\"Resource\\\": [ \\\"arn:aws:iot:us-east-2:<ACCOUNT_ID>:client\\\/${iot:Connection.Thing.ThingName}\\\" ] }, { \\\"Effect\\\": \\\"Allow\\\", \\\"Action\\\": [ \\\"iot:Publish\\\", \\\"iot:Receive\\\" ], \\\"Resource\\\": [ \\\"arn:aws:iot:us-east-2:<ACCOUNT_ID>:topic\\\/${iot:Connection.Thing.ThingName}\\\/*\\\" ] }, { \\\"Effect\\\": \\\"Allow\\\", \\\"Action\\\": [ \\\"iot:Subscribe\\\" ], \\\"Resource\\\": [ \\\"arn:aws:iot:us-east-2:<ACCOUNT_ID>:topicfilter\\\/${iot:Connection.Thing.ThingName}\\\/*\\\" ] } ] }\" } } } }",
     "roleArn":"arn:aws:iam::<ACCOUNT_ID>:role/JITPRole"
    }

    Note: Replace the roleArn value with the IAM Role ARN for your AWS IoT Core service. Replace the value with your AWS account ID. Replace us-east-2 with your AWS Region.

  5. To save the JITP template file, press Esc on your keyboard, followed by :wq!.

  6. Choose Enter to exit the file.

Note: The following IAM policies are included in the example JITP template:

You must be signed in to your AWS account to view the policy links. For more information, see Provisioning templates.

Register your self-signed root CA certificate with AWS IoT Core

  1. Register the device root CA as a CA certificate in AWS IoT Core.

  2. Run the following register-ca-certificate AWS CLI command:

    $ aws iot register-ca-certificate --ca-certificate file://deviceRootCA.pem --verification-cert file://verificationCert.crt --set-as-active --allow-auto-registration --registration-config file://jitp_template.json --region us-east-2

    Note: Replace us-east-2 with the Region where you want to use JITP.

Note: Use the parameter --registration-config to attach the JITP template that you created to the CA certificate. To return the CA certificate's ARN, use the command response.

For more information, see Register your CA certificate.

Create device certificates and perform JITP

Important: Make sure that you use the same directory where you created the original device root CA files.

  1. Download the RootCA1 and save it with the file name awsRootCA.pem.

    Note: The RootCA1 is used for server-side authentication of publish requests to AWS IoT Core. For more information, see CA certificates for server authentication.

  2. Create a device private key. Run the following OpenSSL command:

    $ openssl genrsa -out deviceCert.key 2048
  3. Create a CSR device. Run the following OpenSSL command:

    $ openssl req -new -key deviceCert.key -out deviceCert.csr

    Important: The example JITP template requires the ThingName value to equal the certificate's CommonName value. The template also requires the CountryName value to equal the Country value in the CA certificate. For example:

    Country Name (two-letter code) []:IN
    Common Name (e.g. server FQDN or YOUR name) []: DemoThing

    The JITP template provided in this article also uses the AWS::IoT::Certificate::Country certificate parameter, which requires you to add a value. Other potential certificate parameters include: AWS::IoT::Certificate::Country AWS::IoT::Certificate::Organization AWS::IoT::Certificate::OrganizationalUnit AWS::IoT::Certificate::DistinguishedNameQualifier AWS::IoT::Certificate::StateName AWS::IoT::Certificate::CommonName AWS::IoT::Certificate::SerialNumber AWS::IoT::Certificate::Id

  4. Create a device certificate. Run the following OpenSSL command:

    $ openssl x509 -req -in deviceCert.csr -CA deviceRootCA.pem -CAkey deviceRootCA.key -CAcreateserial -out deviceCert.crt -days 365 -sha256
  5. Combine the root CA certificate and device certificate. Run the following command:

    $ cat deviceCert.crt deviceRootCA.pem > deviceCertAndCACert.crt
  6. Use Eclipse Mosquitto to make a test publish call to AWS IoT Core and initiate the JITP process.

    Note: You can also use the AWS Device SDK to make Publish calls to AWS IoT Core.

    Example Eclipse Mosquitto test publish call command

    Important: Before you run the command, replace a27icbrpsxxx-ats.iot.us-east-2.amazonaws.com with your own endpoint. To confirm your own endpoint, open the AWS IoT Core console. Then, choose Settings. Your endpoint appears in the Custom endpoint pane.

    $ mosquitto_pub --cafile awsRootCA.pem --cert deviceCertAndCACert.crt --key deviceCert.key -h a27icbrpsxxx-ats.iot.us-east-2.amazonaws.com -p 8883 -q 1 -t  foo/bar -i  anyclientID --tls-version tlsv1.2 -m "Hello" -d

    Example response from the Eclipse Mosquitto test publish call command

    Client anyclientID sending CONNECT  
      Error: The connection was lost. // The error is expected for the first connect call

    Note: The test publish call fails the first time. When AWS IoT Core receives the test publish call, it creates a Certificate, Policy, and Thing. It also attaches the Policy to the Certificate, and then attaches the Certificate to the Thing. The next time you perform JITP, the AWS IoT Core policy that was first created is the one that is used. A new AWS IoT Core policy isn't created.

  7. Confirm that the required resources were created by doing the following:
    Open the AWS IoT Core console.
    Choose Manage.
    Choose Things.
    Choose DemoThing.

  8. Verify that the certificate was created and it's in ACTIVE state. Then, choose Policies and verify that the IAM policy is attached.

Use device certificates in general operation

Note: The value of Client ID that is added in the publish command must match the ThingName that was created during the JITP process. The Topic Name added to the publish command must also follow the format ThingName/*. In the next publish call, you can use the deviceCert.crt instead of deviceCertAndCACert.crt.

  1. Open the AWS IoT Core console.

  2. Choose Test.

  3. For Subscription Topic, enter DemoThing/test.

  4. Run the following Eclipse Mosquitto publish call command to AWS IoT Core:

    Important: Replace a27icbrpsxxx-ats.iot.us-east-2.amazonaws.com with your own endpoint before you run the command. To confirm your own endpoint, open the AWS IoT Core console. Then, choose Settings. Your endpoint appears in the Custom endpoint pane. Also, make sure that you use the custom device certificates that were generated by your custom root CA.

    $ mosquitto_pub --cafile awsRootCA.pem --cert deviceCert.crt --key deviceCert.key -h a27icbrpsxxx-ats.iot.us-east-2.amazonaws.com -p 8883 -q 1 -t  DemoThing/test -i  DemoThing --tls-version tlsv1.2 -m "Hello" -d

    After you run the command, the message is received on the AWS IoT Core Test console.

Create additional device certificates

To create more device certificates and register them to AWS IoT Core, repeat the steps outlined in the Create device certificates and perform JITP section.

Other JITP templates

To fetch the ThingName value from the CommonName field of the certificate and to provide admin permissions in the policy, use the following JITP template:

{
 "templateBody":"{ \"Parameters\" : { \"AWS::IoT::Certificate::CommonName\" : { \"Type\" : \"String\" },\"AWS::IoT::Certificate::Country\" : { \"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:*\\\",\\\"Resource\\\":\\\"*\\\"}]}\" } } } }",
 "roleArn":"arn:aws:iam::<ACCOUNT_ID>:role/JITPRole"
}

To fetch the ThingName value from the CommonName field of the certificate and provide a predefined policy name, use the following JITP template:

{
 "templateBody":"{ \"Parameters\" : { \"AWS::IoT::Certificate::CommonName\" : { \"Type\" : \"String\" },\"AWS::IoT::Certificate::Country\" : { \"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\" : { \"PolicyName\" :  \"Policy_Name\"} } } }",
 "roleArn":"arn:aws:iam::<ACCOUNT_ID>:role/JITPRole"
}

Important: Replace Policy_Name with the policy name that you want to use.

AWS OFFICIAL
AWS OFFICIALUpdated a month ago