Question: How can I use JITP with AWS IoT Core?

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. How do I set up JITP with AWS IoT Core?Short descriptionTo set up a JITP environment with AWS IoT Core, first register your CA with AWS IoT Core. Then, attach a provisioning template to your CA.

ResolutionNote: If you receive errors when running AWS Command Line Interface (AWS CLI) commands, make sure that you’re using the most recent AWS CLI version.Create a self-signed root CA and verification certificate1.    If you haven't already done so, install OpenSSL.2.    Create a device root CA private key by running the following OpenSSL command:$ openssl genrsa -out deviceRootCA.key 20483.    Using the VIM text editor, create a custom OpenSSL.conf file. To create and edit a custom OpenSSL.conf file, do the following:Create a custom OpenSSL.conf file by running the following VIM command:$ vi deviceRootCA_openssl.confPress i on the keyboard to edit the .conf file. Then, copy and paste the following into the file:[ req ]distinguished_name       = req_distinguished_nameextensions               = v3_careq_extensions           = v3_ca[ v3_ca ]basicConstraints         = CA:TRUE[ req_distinguished_name ]countryName              = Country Name (2 letter code)countryName_default      = INcountryName_min          = 2countryName_max          = 2organizationName         = Organization Name (eg, company)organizationName_default = AMZPress esc on your keyboard, followed by :wq! to save the .conf file. Then, press Enter to exit the file.Note: To confirm that the OpenSSL.conf file was created, you can run the following Linux command:$ cat deviceRootCA_openssl.conf4.    Create a device root CA certificate signing request (CSR) by running the following OpenSSL command:$ openssl req -new -sha256 -key deviceRootCA.key -nodes -out deviceRootCA.csr -config deviceRootCA_openssl.conf5.    Create a device root CA certificate by running the following OpenSSL command:$ openssl x509 -req -days 3650 -extfile deviceRootCA_openssl.conf -extensions v3_ca -in deviceRootCA.csr -signkey deviceRootCA.key -out deviceRootCA.pem6.    Retrieve the registration code for the AWS Region that you want to use JITP in by running the following AWS CLI command:Important: Make sure that you replace us-east-2 with the Region that you want to use JITP in.$ aws iot get-registration-code --region us-east-27.    Create a verification key by running the following OpenSSL command:$ openssl genrsa -out verificationCert.key 20488.    Create a verification certificate CSR by running the following OpenSSL command:$ openssl req -new -key verificationCert.key -out verificationCert.csrThen, enter the Registration Code in the Common Name field. For example: Common Name (server FQDN or YOUR name) []: xxxxxxxx8a33da. Leave the other fields blank.9.    Create the verification certificate by running the following OpenSSL command:$ openssl x509 -req -in verificationCert.csr -CA deviceRootCA.pem -CAkey deviceRootCA.key -CAcreateserial -out verificationCert.crt -days 500 -sha256Important: The registration code of your root CA’s Region is required for the verification certificate to be certified by AWS IoT Core.For more information, see Just-in-time provisioning.Create a JITP template1.    Create an AWS Identity and Access Management (IAM) role for your AWS IoT Core service and name it JITPRole. For instructions, see Create a logging role (steps one and two).Important: You must include the IAM role’s Amazon Resource Name (ARN) in the following JITP template.2.    Using the VIM text editor, create a JITP template JSON file by doing the following:Create a JITP template JSON file by running the following VIM command:$ vi jitp_template.jsonImportant: Make sure that you save the template with the file name jitp_template.json.Press i on the keyboard to edit the JITP template. 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"}Important: Replace the roleArn value with the IAM Role ARN for your AWS IoT Core service. Replace the <ACCOUNT_ID> value with your AWS account ID. Replace us-east-2 with the AWS Region that you're using. Press esc on your keyboard, followed by :wq! to save the JITP template file. Choose Enter to exit the file.Note: The following IAM policies are included in the example JITP template:AWSIoTLoggingAWSIoTRuleActionsAWSIoTThingsRegistrationYou 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 CoreRegister the device root CA as a CA certificate in AWS IoT Core by running the following register-ca-certificate AWS CLI command:Important: Make sure that you replace us-east-2 with the Region that you want to use JITP in.$ 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-2Note: Adding the parameter --registration-config attaches the JITP template that you created to the CA certificate. The command response returns the CA certificate's ARN.For more information, see Register your CA certificate.Create device certificates and perform JITPImportant: 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 by running the following OpenSSL command:$ openssl genrsa -out deviceCert.key 20483.    Create a device CSR by running the following OpenSSL command:$ openssl req -new -key deviceCert.key -out deviceCert.csrImportant: 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) []:INCommon Name (eg. server FQDN or YOUR name) []: DemoThingThe 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::Id4.    Create a device certificate by running the following OpenSSL command:$ openssl x509 -req -in deviceCert.csr -CA deviceRootCA.pem -CAkey deviceRootCA.key -CAcreateserial -out deviceCert.crt -days 365 -sha2565.    Combine the root CA certificate and device certificate by running the following command:$ cat deviceCert.crt deviceRootCA.pem > deviceCertAndCACert.crt6.    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 commandImportant: Replace a27icbrpsxxx-ats.iot.us-east-2.amazonaws.com with your own endpoint before running the command. To confirm your own endpoint, open the AWS IoT Core console. Then, choose Settings. Your endpoint is listed 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" -dExample response from the Eclipse Mosquitto test publish call commandClient anyclientID sending CONNECT    Error: The connection was lost. // The error is expected for the first connect callNote: 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 IoT policy that was first created is the one that is used. A new IoT policy isn't be created.7.    Confirm the required resources were created by doing the following: Open the AWS IoT Core console. Choose Manage. Choose Things. Choose DemoThing.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 operationNote: The value of Client ID that is added in the publish command must be the same as 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 running 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" -dAfter running the command, you will see that the message is received on the AWS IoT Core Test console.Create additional device certificatesTo 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 templatesTo 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 of your choice.