Just-in-time provisioning

With Just-in-time provisioning or JITP devices can get automatically registered when they connect for the first time to AWS IoT Core. To use JITP you must bring your own CA and enable automatic registration for the CA. You also need to associate a provisioning template with your own CA certificate. Device certificates are issued by your own CA. You will use the CA that you have created and registered with AWS IoT already.

In this exercise you will prepare your own CA for JITP and register a new device simply by connecting it to AWS IoT.

Directory

Use the directory ~/ACM_PCA for the exercises in this chapter.

cd ~/ACM_PCA

Shell variables

Make sure that the shell variables CA_ARN and CA_CERTIFICATE_ID are set to the arn of your private CA and to the id of your CA certificate registered with AWS IoT.

Use the following commands to verify if your shell variables are set.

echo $CA_ARN
echo $CA_CERTIFICATE_ID

If any of the variables is not set assign the CA arn or the CA certificate id to the related variable.

You can find your CA arn with:

aws acm-pca list-certificate-authorities

The CA certificate id can be found with:

aws iot list-ca-certificates

Enable JITP for your own CA

Enable JITP for your CA by attaching a provisioning template to the CA. An IAM role required for JITP has been already created for you and its arn has been stored in the shell variable $ARN_IOT_PROVISIONING_ROLE.

Store the template body in a shell variable

TB="{ \\\"Parameters\\\" : { \\\"AWS::IoT::Certificate::Id\\\" : { \\\"Type\\\" : \\\"String\\\" }, \\\"AWS::IoT::Certificate::CommonName\\\" : { \\\"Type\\\" : \\\"String\\\" }, \\\"AWS::IoT::Certificate::Country\\\" : { \\\"Type\\\" : \\\"String\\\" } }, \\\"Resources\\\" : { \\\"thing\\\" : { \\\"Type\\\" : \\\"AWS::IoT::Thing\\\", \\\"Properties\\\" : { \\\"ThingName\\\" : {\\\"Ref\\\" : \\\"AWS::IoT::Certificate::CommonName\\\"}, \\\"AttributePayload\\\" : { \\\"Country\\\" :  {\\\"Ref\\\" : \\\"AWS::IoT::Certificate::Country\\\"} }, \\\"ThingGroups\\\" : [\\\"bulk-group\\\"] } }, \\\"certificate\\\" : { \\\"Type\\\" : \\\"AWS::IoT::Certificate\\\", \\\"Properties\\\" : { \\\"CertificateId\\\": { \\\"Ref\\\": \\\"AWS::IoT::Certificate::Id\\\" }, \\\"Status\\\" : \\\"ACTIVE\\\" } }, \\\"policy\\\" : { \\\"Type\\\" : \\\"AWS::IoT::Policy\\\", \\\"Properties\\\" : { \\\"PolicyName\\\": \\\"$IOT_POLICY\\\" } } } }"

Verify the content of $TB

echo $TB

Attach the provisioning template (stored in the variable $TB) to the CA certificate

aws iot update-ca-certificate --certificate-id $CA_CERTIFICATE_ID \
	  --no-remove-auto-registration \
	  --new-auto-registration-status ENABLE \
	  --registration-config "{\"templateBody\": \"$TB\",\"roleArn\": \"$ARN_IOT_PROVISIONING_ROLE\"}"

Get information about your CA certificate and verify that the provisioning template has been attached

aws iot describe-ca-certificate --certificate-id $CA_CERTIFICATE_ID

The output of this command should contain the following information (amongst others):

        ...
        "autoRegistrationStatus": "ENABLE",
        ...
    },
    "registrationConfig": {
        "templateBody": "{...

Connect a device with a certificate from your own CA

Create a device certificate

Set the name for your device cert

deviceCert=deviceJITPCert

Generate key and CSR

openssl req -nodes -new -newkey rsa:2048 \
            -keyout $deviceCert.key \
            -out $deviceCert.csr \
            -subj "/C=DE/CN=my-jitp-device"

Issue a certificate from the CSR

aws acm-pca issue-certificate \
	--certificate-authority-arn $CA_ARN \
	--csr file://./$deviceCert.csr \
	--signing-algorithm "SHA256WITHRSA" \
	--validity Value=365,Type="DAYS" \
	--idempotency-token $(date +'%Y%m%d%H%M%S')

This command outputs the arn of your certificate. Make a note of the arn because it will be used in subsequent commands.

It can take some moments until ACM PCA has issued the certificate. So wait until ACM PCA the certificate has been issued

aws acm-pca wait certificate-issued \
	--certificate-authority-arn $CA_ARN \
	--certificate-arn [REPLACE_WITH_YOUR_CERTIFICATE_ARN]

Get certificate from ACM PCA. The certificate is returned in a JSON object so the output of the command will be written to the file $deviceCert.json

aws acm-pca get-certificate \
	--certificate-authority-arn $CA_ARN \
	--certificate-arn [REPLACE_WITH_YOUR_CERTIFICATE_ARN] > $deviceCert.json

If you are interested take a look at the result

cat $deviceCert.json

Store the device certificate in a file

jq -r '.Certificate' $deviceCert.json > ${deviceCert}.crt

Store the device certificate together with the certificate of your CA in one file. This file will be used for the first time when your device connects to AWS IoT and gets registered. After it has been registered you only need the file containing your device certificate.

jq -r '.Certificate' $deviceCert.json > ${deviceCert}AndCACert.crt
cat acm-pca-root-ca.pem >> ${deviceCert}AndCACert.crt

In the AWS IoT Core console subscribe to $aws/events/#

Auto register your device by publishing a message

# publish
mosquitto_pub --cafile ~/root.ca.bundle.pem \
  --cert ${deviceCert}AndCACert.crt \
  --key $deviceCert.key \
  -h $IOT_ENDPOINT -p 8883 -q 1 -t  ji/tp \
  -i  $deviceCert --tls-version tlsv1.2 -m '{"let-me": "in"}' -d

The command will produce an error message like:

Client [device_name] sending CONNECT
Error: The connection was lost.

Don’t worry, this is a normal behaviour as AWS IoT disconnects the client when the automatic registration process of the device has been started.

Verify if the device was created either in the AWS IoT Core console or on the command line

aws iot list-things

or

aws iot describe-thing --thing-name my-jitp-device

Subscribe to ji/tp and publish again the message above. The device should be now provisioned and ready to operate

# publish
mosquitto_pub --cafile ~/root.ca.bundle.pem \
  --cert ${deviceCert}.crt \
  --key $deviceCert.key \
  -h $IOT_ENDPOINT -p 8883 -q 1 -t  ji/tp -i $deviceCert \
  --tls-version tlsv1.2 -m '{"let-me": "in"}' -d