AWS IoT Provisioning Templates and Referenced Policies
Tags: cloud, aws, iot, jitp
Published: 2023-01-29 15:47:18

---
title: AWS IoT Provisioning Templates and Referenced Policies
published: true
date: 2023-01-17 00:00:00 UTC
tags:
  - cloud
  - aws
  - iot
  - jitp
canonical_url: https://carstenrn.com/2023/01/aws-iot-many-ways-to-register-things/
---

Lately, I had to work a bit with AWS IoT. One aspect thereof is the device registration with [just-in-time provisioning (JITP)](https://aws.amazon.com/premiumsupport/knowledge-center/aws-iot-core-jitp-setup/). In essence, with JITP you need to provide a template that configures all relevant resources of a newly registered IoT device: parameters like the device’s name, its certificate, and policies to be attached to the certificate. Said certificate can then be used by its respective IoT device to [authenticate with AWS IoT](https://docs.aws.amazon.com/iot/latest/developerguide/x509-client-certs.html).

## The Basics

I mentioned that, with JITP, you provide a template for device provisioning: a [**Provisioning Template**](https://docs.aws.amazon.com/iot/latest/developerguide/provision-template.html). As per AWS documentation, this template is of the general form:

```
{
    "Parameters": { ... },
    "Resources": {
        "thing": { ... },
        "certificate": { ... },
        "policy": { ... }
    }
}

```

Certificates can have `0..n` attached policies. A policy can be attached to `0..m` certificates.

In particular, policies can be attached to certificates on certificate creation, but also anytime thereafter. This implies that a certificate referred to in a provisioning template **could** already have the policy (or: policies) attached referred to in the same template!

## The Question

If a certificate could already come with the desired policies attached, **is it then necessary to refer to a policy in the provisioning template**? The [AWS documentation](https://docs.aws.amazon.com/iot/latest/developerguide/provision-template.html) is contradicting here: it states that (emphasis is mine)

> The Resources section of the template body declares the resources **required** for your device to communicate with AWS IoT: a thing, a certificate, and **one or more IoT policies**.

while in a later note under “Policy resources”, it is stated that

> **If** a Policy section **is present** …

So either `1..n`, `0..1`, or `0..n` policy sections are allowed under `"Resources"`.

## Let’s find out

We use the `aws-cli` to check three different cases: Can we register an IoT device where

1. … neither the certificate nor the provisioning template has an attached policy?
2. … the certificate has no policy attached yet, but a policy is listed in the provisioning template?
3. … both the certificate _and_ the provisioning template has an attached policy?

Let’s briefly state the expectations I had when formulating the above test cases:

1. I kinda expected this to be forbidden as it does not make that much sense. We would end with an IoT device that has a certificate, which however does not permit anything, rendering it essentially useless.
2. IMHO, this is the common use case: we use a certificate created before IoT device registration and now want to have a policy attached to it. Although it feels a bit like a side effect of the device provisioning, I expected that after the IoT device registration finished, the certificate would have the policy referred to in the provisioning template attached to it.
3. A degenerated variant of 2. I expected this to work as well, both if the certificate’s policies equal those referred to in the provisioning template as well if the sets intersect and even if they are disjoint.

Now to our test script:

```
#!/usr/bin/env sh
aws iot register-thing \
    --template-body file://register-thing-template.json \
    --parameters file://register-thing-parameters.json

```

The `register-thing-template.json` contains the attributes (e.g., name) for our IoT device and a reference to an IoT certificate:

```
{
    "Parameters": {
        "thingName": {
            "Type": "String"
        },
        "certificateId": {
            "Type": "String"
        }
    },
    "Resources": {
        "thing": {
            "Type": "AWS::IoT::Thing",
            "Properties": {
                "ThingName": {
                    "Ref": "thingName"
                }
            }
        },
        "certificate": {
            "Type": "AWS::IoT::Certificate",
            "Properties": {
                "CertificateId": {
                    "Ref": "certificateId"
                },
                "Status": "ACTIVE"
            }
        }
    }
}

```

For scenarios 2. and 3. our provisioning template has to refer to a an existing policy. In these cases, add the following section under `Resources`:

```
{
    "Parameters": { ... },
    "Resources": {
        ...,
        "policy": {
            "Properties": {
                "PolicyName": "sample-policy"
            },
            "Type": "AWS::IoT::Policy"
        }
    }
}

```

The above provisioning template is fixed, meaning it just contains the parts that apply to all IoT devices we would like to register with it. The changeable <sup id="fnref:1"><a href="#fn:1" role="doc-noteref">1</a></sup> parts are injected through parameters. This is our exemplary `register-thing-parameters.json`:

```
{
    "thingName": "sample-device-001",
    "certificateId": "7e14b8107baad9658eedd2dc286dfabfdc2457e3bb33cbc34a27cf1b87897dd0"
}

```

Executing our script for all three scenarios yields that indeed, policies are **not mandatory** , neither in IoT certificates nor in provisioning templates. Moreover, policies mentioned in the provisioning template are **added** (think: set-add, not list-add) to the policies already attached to the referred certificate. So… our expectations are met by reality. 🎉

## One More Thing

How about the names `thing`, `certificate`, and `policy` in provisioning templates? Are they keywords and thus fixed? The [AWS documentation](https://docs.aws.amazon.com/iot/latest/developerguide/provision-template.html) does not give a definite answer, but the fact that we need to specify a type (`AWS::IoT::Thing`, …) makes it most likely that these names are **completly arbitrary**. **And indeed they are** : We can change, for instance, the name `policy` to `myWonderfulPolicy` and observe that the IoT device registration still works just as we expect it to.

* * *

1. Random fact: The misspelling “changable” apparently is quite common in tech. I read _somewhere_ (but forgot where exactly) an article stating exactly this. Funny enough that we as engineers are usually the group of people having access to the most technologically advanced tools, including spell checkers… 😇 [↩︎](#fnref:1)