The Internet of Things on AWS – Official Blog
Just-in-Time Registration of Device Certificates on AWS IoT
In an earlier blog post about certificates, we discussed how use-your-own-certificate support in AWS IoT lets customers use device certificates signed and issued by their own certificate authority (CA) to connect and authenticate with AWS IoT. This is an alternative to using certificates generated by AWS IoT.
Using your own certificate with AWS IoT is a two-step process:
- The first step is to register the CA certificate that signed and issued the device certificates.
- After registration, any device certificate that was signed by the CA can be registered with AWS IoT and used for authentication thereafter.
Now, with support for just-in-time registration (JITR) of CA-signed certificates, AWS IoT eliminates the second step.
In this blog post, I will explain how JITR works and how it can be used to set up a workflow that activates device certificates and attaches policies to them automatically. I will also walk you through steps for deactivating a CA certificate and revoking device certificates.
You will do the following:
- Create, register, and activate a CA certificate that will be used to sign your device certificate.
- Enable auto-registration of certificates.
- Create device certificates signed by the CA and install them on your device.
- Create and attach a rule with an AWS Lambda action that activates the certificate, and then creates and attaches policies to the certificate.
- Connect to AWS IoT using the device certificate.
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 certificate. After these steps, your device certificate will be ready to connect and authenticate with AWS IoT.
In this blog post, I assume you are familiar with AWS IoT and the process of creating an AWS IoT certificate. You will use the AWS CLI and OpenSSL to perform the procedures. If you don’t have the AWS CLI installed, follow these steps. If you already have the AWS CLI, make sure you are using the most recent version.
For information about authentication in AWS IoT or how to use AWS IoT-generated certificates, see the AWS IoT Developer Guide.
Registering Your CA Certificate
If you are a manufacturer, you have purchased CA certificates from vendors like Symantec or Verisign or you have your own CA. To use your own X.509 certificates that have been signed by your CA certificate, AWS IoT must first verify that you not only own the CA certificate, but that you also have access to its private key. The process for validating ownership of a CA certificate is done through a challenge and response workflow.
Let’s start by using openssl in a terminal to create your sample CA certificate. In the real world, the signing or intermediate certificates would be issued by your CA vendor. This sample CA certificate is used later in the walkthrough to sign a device certificate that you register with AWS IoT:
$ openssl genrsa -out sampleCACertificate.key 2048 $ openssl req -x509 -new -nodes -key sampleCACertificate.key -sha256 -days 365 -out sampleCACertificate.pem
For simplicity, we are creating and registering the root CA certificate. In reality, the intermediate CA certificate would be signed by the root CA that signs the device certificates. In that case, you register the intermediate CA certificate with AWS IoT.
Now that you’ve created a sample CA certificate, you will register it with AWS IoT. When you register a CA certificate with AWS IoT, you follow a workflow to verify that you have access to both the CA certificate and the private key associated with the CA certificate. To verify ownership of the private key, you generate a verification certificate using the CA certificate, the private key, and a registration code that you generate from AWS IoT.
The registration workflow first requires retrieving the registration code. You can use the AWS CLI or the Register Certificate section in the AWS IoT console to get the registration code.
To use the AWS CLI, run the following command:
$ aws iot get-registration-code
This command will return a randomly generated, unique registration code that is bound to your AWS account. This registration code is long-lived. It does not expire until you delete it.
Next, you will use the registration code to create a CSR:
$ openssl genrsa -out privateKeyVerification.key 2048 $ openssl req -new -key privateKeyVerification.key -out privateKeyVerification.csr
During the CSR creation process, you will be prompted for information. Enter the registration code into the Common Name field of the verification certificate:
... Organization Name (eg, company) []: Organizational Unit Name (eg, section) Common Name (e.g. server FQDN or YOUR name) []: XXXXXSAMPLEREGISTRATIONCODEXXXXX EMAIL ADDRESS []:
The registration code establishes that the generated verification certificate was created specifically for registering the CA certificate with AWS IoT, and that the verification certificate is not a previously issued certificate.
Now that you have a CSR that includes the registration code, use your first sample CA certificate and the CSR to create a new certificate:
$ openssl x509 -req -in privateKeyVerification.csr -CA sampleCACertificate.pem -CAkey sampleCACertificate.key -CAcreateserial -out privateKeyVerification.crt -days 365 -sha256
When you register your CA certificate with AWS IoT, the combination of the registration code, verification certificate signed with the CA private key, and the CA certificate are used to verify ownership of the CA private key.
Next, you will use the verification certificate to register your sample CA certificate:
$ aws iot register-ca-certificate --ca-certificate file://sampleCACertificate.pem --verification-certificate file://privateKeyVerification.crt
You can make a describe-ca-certificate call to get the information on the registered CA certificate. You will use the certificate ID of the registered CA returned in the response of the previous CLI command.
$ aws iot describe-ca-certificate --certificate-id <certificateId>
Next, you will activate the CA certificate. By default, the CA certificate will be registered in an INACTIVE state. At the time of the registration of the device certificate, AWS IoT will consult the status of its registered CA certificate and will allow the registration of the device certificate only if the CA certificate is in an ACTIVE state. Use the update-ca-certificate CLI command to change the status of the CA certificate. Alternatively, you can register the CA certificate in the ACTIVE state by passing the set-as-active flag at the time of registration:
$ aws iot update-ca-certificate --certificate-id <certificateId> --new-status ACTIVE
By default, the auto-registration-status of the registered CA certificate is disabled. That means any device certificate issued by the registered CA will not be auto-registered by default when it first connects to the AWS IoT service. However, you can use the register-certificate CLI command to explicitly register the device certificate. If the auto-registration-status is enabled for a CA certificate, the device certificate issued by that CA will be auto-registered, if not already registered, when it connects to AWS IoT for the first time. To opt in for the auto-registration of the device certificates issued by a registered CA, set the auto-registration-status for the CA certificate to ENABLE.
You can enable the auto-registration-status through the update-ca-certificate CLI command. Alternatively, you can register the CA certificate with the auto-registration-status enabled by passing the --allow-auto-registration flag to the register-ca-certificate CLI command.
$ aws iot update-ca-certificate --certificate-id <caCertificateId> --new-auto-registration-status ENABLE
Device Certificate Registration Event and Action
When a device attempts to connect with an X.509 certificate that is not known to AWS IoT but was signed by a CA that was registered with AWS IoT, the device certificate will be auto-registered by AWS IoT in a new PENDING_ACTIVATION state. PENDING_ACTIVATION means that the device certificate was auto-registered and is awaiting activation. Only AWS IoT can mark the status of a certificate as PENDING_ACTIVATION. If you connect with a certificate in PENDING_ACTIVATION state, a TLS handshake failure will occur because only ACTIVE certificates are authenticated with AWS IoT. For this reason, you need to change the status of the registered certificate from PENDING_ACTIVATION to ACTIVE so that it can be successfully authenticated.
When AWS IoT auto-registers a certificate or when a certificate in PENDING_ACTIVATION status connects, it publishes a message to the following MQTT topic:
$aws/events/certificates/registered/<caCertificateID>
where the caCertificateId is the ID of the CA certificate that issued the device certificate.
The message published to this topic has the following structure:
{ "certificateId": "<certificateID>", "caCertificateId": "<caCertificateId>", "timestamp": "<timestamp>", "certificateStatus": "PENDING_ACTIVATION", "awsAccountId": "<awsAccountId>", "certificateRegistrationTimestamp": "<certificateRegistrationTimestamp>" }
You can subscribe or attach any AWS IoT rule to the registration topic. The attached AWS IoT rules can then take some action based on the messages received. For example, an AWS IoT rule in your account can listen on the $aws/events/certificates/registered/+ topic to build an Amazon DynamoDB table of all the registered certificates. The general recommendation is to attach an AWS IoT rules engine action to the registration topic that will perform the bootstrapping or provisioning steps (like consulting your CRLs) and then activate/deactivate/revoke the certificate, create and attach the policies to the certificate, and so on.
In the following example, we will create a topic rule with an AWS Lambda action on the registration topic that will activate the certificate and create and attach a policy.
Use the AWS Lambda console to create the AWS Lambda function:
- Sign in to the AWS Management Console and open the AWS Lambda console at https://console.aws.amazon.com/lambda/home?region=us-east-1.
- Choose Create an AWS Lambda function.
- On the Configure function page, type a name and description for the AWS Lambda function. In Runtime, choose Node.js 4.3.
- Scroll down to the AWS Lambda function code section of the page. Replace the existing code with this sample code.
- Scroll down to the AWS Lambda function handler and role section of the page. For Role, choose Create a custom role. When the IAM console opens, you can create an IAM role that AWS Lambda can assume when executing the AWS Lambda function.
- In the navigation pane, choose Create New Role.
- For Role name, type a role name.To edit the role’s policy to give it permission to update the certificate and create and attach the policy:
- Choose View Policy Document.
- Replace the policy document with the following:
{ "Version":"2012-10-17", "Statement":[ { "Effect":"Allow", "Action":[ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource":"arn:aws:logs:*:*:*" }, { "Effect":"Allow", "Action":[ "iot:UpdateCertificate", "iot:CreatePolicy", "iot:AttachPrincipalPolicy" ], "Resource":"*" } ] }
- Choose Allow.
- Leave the settings on the Advanced settings page at their defaults, and choose Next.
- On the Review page, choose Create function.
Creating an AWS Lambda Rule
Now that you have created an AWS Lambda function, you can create a rule that invokes the function.
- In the AWS IoT console, choose Create a resource.
- Choose Create a rule.
- Type a name and description for the rule.
- Enter the following settings for the rule:
SQL version: 2016-03-23-beta
Attribute: *
Topic filter: $aws/events/certificates/registered/<caCertificateID> Note: Replace <caCertificateId> with the ID of the registered CA certificate. - For Choose an action, choose Insert this message into a code function and execute it (AWS Lambda).
- From Function name, choose your AWS Lambda function name, and then choose Add action.
- Choose Create to create your AWS Lambda function.
You also need to grant permissions to the AWS IoT service principal to invoke the AWS Lambda function on your behalf when the MQTT message is published on the registration topic.
Note: If you created the rule through the AWS IoT console, you can skip this step. The console does this for you when you create the AWS Lambda rule.
You will use the AWS Lambda AddPermission API to grant permissions:
aws lambda add-permission --function-name <lambda-function-name> --region us-east-1 --principal iot.amazonaws.com --source-arn <rule-arn> --source-account <your-aws-account> --statement-id Id-123 --action "lambda:InvokeFunction"
Auto-registration of a Device Certificate Signed by Your CA Certificate
Now that you’ve created, registered, and activated a sample CA certificate with auto-registration-status enabled and configured a rule with an AWS Lambda action to activate the certificate and attach policies, use the CA certificate to create a new device certificate and auto-register it when it first connects to AWS IoT.
Enter the following commands in your terminal to create a device certificate:
$ openssl genrsa -out deviceCert.key 2048 $ openssl req -new -key deviceCert.key -out deviceCert.csr $ openssl x509 -req -in deviceCert.csr -CA sampleCACertificate.pem -CAkey sampleCACertificate.key -CAcreateserial -out deviceCert.crt -days 365 -sha256
Next, try to connect to AWS IoT using the device certificate. Because you’ve completed the preceding steps, your device certificates will be auto-registered during the TLS handshake when it connects to AWS IoT for the first time. At the time of connection, you need to send both the device certificate and its registered CA certificate.
Create a certificate file that contains the device certificate and its registered CA certificate. Here is the Linux command:
$ cat deviceCert.crt sampleCACertificate.pem > deviceCertAndCACert.crt
In the following example, you will use the MQTT Mosquitto client to connect and publish to AWS IoT using the device certificate:
$ mosquitto_pub --cafile root.cert --cert deviceCertAndCACert.crt --key deviceCert.key -h <prefix>-ats.iot.us-east-1.amazonaws.com -p 8883 -q 1 -t foo/bar -i anyclientID --tls-version tlsv1.2 -m "Hello" -d
Note: The root.cert is the AWS IoT root certificate. The AWS IoT root CA certificate is used by a device to verify the identity of the AWS IoT servers. Click here to download the root certificate. Save this file to your desktop and name it “root.cert”.
You will see a TLS failure when you run the command because AWS IoT disconnects the connection after the registration of the device certificate. AWS IoT has registered the certificate in the PENDING_ACTIVATION state and won’t let it connect and authenticate unless the certificate is marked ACTIVE. The client or device should implement an automatic reconnect strategy when it is disconnected due to the TLS error. The device should also implement a back-off strategy (that is, increase the time between retries) to avoid unnecessary network traffic and allow your own activation logic to complete before devices attempt to reconnect.
The commands to connect to AWS IoT with the device certificate whose CA has been registered will lead to the auto-registration of the device certificate during the TLS handshake. An MQTT registration event will be published on the registration topic and trigger the attached Lambda rule action to activate the certificate and attach the policy to it. This will complete the registration and provisioning of the device certificate. It can now be used for authentication and authorization with AWS IoT. After a device certificate is registered with AWS IoT, you can interact with it in a way that’s similar to a device certificate generated by AWS IoT. You can activate/deactivate /revoke certificates, attach policies, and associate things to your device certificates. In addition, you can manage the lifecycle of that device certificate in AWS IoT by deactivating, revoking, or activating the certificate in your AWS account.
Deactivate the CA Certificate
During device certificate registration, AWS IoT will check if the associated CA certificate is active. If the CA certificate is inactive, AWS IoT will not allow the device certificate to be registered. This feature provides you with the flexibility to manage the lifecycle of device certificates signed by the registered CA that are yet to be registered with AWS IoT. By marking the status INACTIVE, you prevent any new device certificates issued by the compromised CA to be registered in your account. You can run the following command to deactivate the CA certificate:
$ aws iot update-ca-certificate --certificate-id <certificateId> --new-status INACTIVE
Note: Running this command will not deactivate all of your registered device certificates. It will prevent new device certificates from being registered.
Revoke the Device Certificate
If you wish to revoke a registered device certificate, use the following command to revoke it:
$ aws iot update-certificate --certificate-id <certificateId> --new-status REVOKED
Use the list-certificates-by-ca CLI command to get a list of registered device certificates, sorted by the date of registration, that are issued by the CA certificate:
$ aws iot list-certificates-by-ca --ca-certificate-id <caCertificateId>
If an error or exception occurs during the auto-registration of the device certificates, AWS IoT will send the events or message to CloudWatch Logs. To set up CloudWatch Logs for your account, see the AWS IoT Developer Guide.
Conclusion
We hope you found these steps (using your own device certificate with AWS IoT, auto-registration of device certificates, and deactivating CA certificates) useful and will use them to provision and register your device certificates with AWS IoT. Give it a try and feel free to leave your feedback in the comments.