Just-in-time registration

Just-in-time registration or JITR is another option beside just-in-time provisioning to register a device with AWS IoT when it connects for the first time.

When you connect to AWS IoT with the device certificate for the first time, the service will detect an unknown certificate signed by a registered CA and will auto-register the device certificate. On successful registration, AWS IoT will publish a registration message on a reserved MQTT topic and disconnect the client.

This MQTT registration event will trigger the attached AWS Lambda rules engine action, which will complete the provisioning of the device. After these steps, your device certificate will be ready to connect and authenticate with AWS IoT.

In this exercise you will setup just-in-time registration (JITR) with your own CA (ACM PCA) and an AWS Lambda function. The Lambda function will complete the following steps to register the device with AWS IoT:

  • As input the Lambda function receives amongst others the device certificate id, ca certificate id and device certificates status
  • The common name (CN) from the device certificate is used to create a thing in the device registry
  • An IoT policy named jitr_Policy is created if it doesn’t exist
  • The device certificate is activated
  • The device certificate is attached to the thing name
  • The IoT policy is attached to the device certificate

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.

You have learned in the JITP exercise to verify that the variables have been set.

Prepare your CA for JITR

First you need to remove JITP settings from the CA

aws iot update-ca-certificate --certificate-id $CA_CERTIFICATE_ID \
  --remove-auto-registration \
  --new-auto-registration-status DISABLE

Verify that the provision template and role arn have been removed from the CA

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

Set up JITR

To set up JITR you need to enable auto registration for your own CA, create a Lambda function which provisions your device and create a topic rule which calls the Lambda function once the device certificate gets registered.

Enable just-in-time registration for your CA

aws iot update-ca-certificate --certificate-id $CA_CERTIFICATE_ID \
  --new-auto-registration-status ENABLE

Verify that the auto registration status is set to ENABLE

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

The output of the previous command should contain:

        ...
        "autoRegistrationStatus": "ENABLE",
        ...

Create a Lambda function to provision your devices. The role that is required to create the Lambda function was already created for you and copied to the shell variable $ARN_LAMBDA_ROLE

# change to the directory where the lambda is stored
cd ~/provisioning/jitr

The Lambda function is implemented in Python 3.7 and uses the pyOpenSSL library to parse the certificate. As the pyOpenSSL library is not installed by default in the Lambda environment an installation package as zip file has been created already for you. This zip file will be used to create the Lambda function.

# create the lambda function
aws lambda create-function \
	--region $REGION \
	--function-name jitr \
	--zip-file fileb://./jitr-lambda.zip \
	--role $ARN_LAMBDA_ROLE \
	--handler lambda_function.lambda_handler \
	--runtime python3.7 \
	--timeout 30 \
	--memory-size 256

Verify that the lambda function has been created

aws lambda list-functions

Create an IoT topic rule. With this rule the Lambda function that you just created is called when a device certificate is auto-registered.

To create the topic rule we need to have the arn of the Lambda function. Assign the function arn to the shell variable ARN_LAMBDA:

ARN_LAMBDA=$(aws lambda get-function --function-name jitr | jq -r '.Configuration.FunctionArn')

# verify the variable content
echo $ARN_LAMBDA

Create the IoT topic rule

aws iot create-topic-rule --rule-name JITRRule \
  --topic-rule-payload "{
        \"sql\": \"SELECT * FROM '\$aws/events/certificates/registered/#' WHERE certificateStatus = \\\"PENDING_ACTIVATION\\\"\",
        \"description\": \"Rule for JITR\",
        \"actions\": [
            {
                \"lambda\": {
                    \"functionArn\": \"$ARN_LAMBDA\"
                }
            }
        ]
     }"

Verify that the topic rule has been created

aws iot get-topic-rule --rule-name JITRRule

Add a permission to the lambda function to allow the AWS IoT to invoke the function. For adding the permissions we need the topic rule arn and will store it into a shell variable

# get you AWS account id
ACCOUNT_ID=$(aws sts get-caller-identity | jq -r '.Account')

# verify that the variable has been set
echo $ACCOUNT_ID

# store topic rule arn
ARN_TOPIC_RULE=$(aws iot get-topic-rule --rule-name JITRRule | jq -r '.ruleArn')

# verify that the variable has been set
echo $ARN_TOPIC_RULE

# add permissions to the Lambda
aws lambda add-permission --function-name jitr \
  --region $REGION --principal iot.amazonaws.com \
  --source-arn $ARN_TOPIC_RULE --source-account $ACCOUNT_ID \
  --statement-id Id-123 --action "lambda:InvokeFunction"

# verify the permissions of the function
aws lambda get-policy --function-name jitr

Connect a device with a certificate from your own CA

Create device certificate in the same way you did for JITP but use a different name for deviceCert and the common name my-jitr-device.

Change to the certs directory

cd ~/ACM_PCA

Set a name for your device cert

deviceCert=deviceJITRCert

Create a key and CSR

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

Issue a certificate with ACM PCA. You learned already howto do this in the section about just-in-time provisioning.

Create a thing key, certificate and connect to AWS IoT like you did in the JITP section of this workshop.

Connect to AWS IoT to initiate the JITR process

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

To verify if the JITR process finished successful try to publish a message to the topic dt/my-jitr-device/welcome

mosquitto_pub --cafile ~/root.ca.bundle.pem \
  --cert ${deviceCert}.crt \
  --key $deviceCert.key \
  -h $IOT_ENDPOINT -p 8883 -q 1 -t  dt/my-jitr-device/welcome -i my-jitr-device \
  --tls-version tlsv1.2 -m '{"i am": "just-in-time registered"}' -d

If the message arrives the device has been provisioned successfully.

In case messages are not published successfully you need to troubleshoot your setup:

  • Is your thing in the device registry: aws iot describe-thing --thing-name my-jitr-device
  • The IoT policy jitr_Policy must have been created: aws iot get-policy --policy-name jitr_Policy
  • Is a certificate attached to your thing and is the policy jitr_Policy attached to the certificate
  • Did you use the same names for the thing, topic as described in the instructions or did you used different ones?
  • Check the CloudWatch logs for the lambda and AWS IoT for errors