[AWS IoT] Fleet Provisioningで証明書発行と同時に任意の固有情報を返してみました

2021.03.19

1 はじめに

CX事業本部の平内(SIN)です。

AWS IoT Coreへの接続で使用する証明書は、レジストリへの登録が必要ですが、これを予め登録すること無く、初回接続時に発行・登録しくみが提供されています。

  • Fleet Provisioningによる登録
  • JITRによる登録
  • JITPによる登録

目的はそれるのですが、「初回接続」を「デバイスの初期化処理」と捉えた場合、このタイミングで何らかの固有情報を、クラウド側からデバイス側に送りたいというようなニーズもあるかも知れません。

証明書を受け取ってから改めて要求させても良いのでしょうが、「証明書発行時に、併せて固有情報を返せると便利かも」という事で少し試してみました。

試したのは、Amazonが管理するCAを利用できるFleet Provisioningです。

2 テンプレート作成

最初に、AWSコンソールから、簡単にテンプレートを作成しています。

ここでは、プロビジョニング前のフック(オプション) でLambdaを登録し、最終的に、このLambdaから固有情報を返す想定です。

また、デバイスのキーと値のペアを選択するにチェックを入れ、DeviceConfigurationのキーを追加しておきます。

「プロビジョニングデバイスに構成情報を送信する」では、1つだけキーと値を設定しています。 とりあえずは、これで、固定値が返される状態になっています。

下記が、生成されたテンプレートです。

{
  "Parameters": {
    "SerialNumber": {
      "Type": "String"
    },
    "AWS::IoT::Certificate::Id": {
      "Type": "String"
    }
  },
  "Resources": {
    "certificate": {
      "Properties": {
        "CertificateId": {
          "Ref": "AWS::IoT::Certificate::Id"
        },
        "Status": "Active"
      },
      "Type": "AWS::IoT::Certificate"
    },
    "policy": {
      "Properties": {
        "PolicyName": "default_policy"
      },
      "Type": "AWS::IoT::Policy"
    }
  },
  "DeviceConfiguration": {
    "message": "default"
  }
}

サンプルコードを使用して、アクセスしてみると、証明書の発行と同時に、設定した固定値が返されていることを確認できます。

aws/aws-iot-device-sdk-python-v2/samples/fleetprovisioning.py

% python3 fleetprovisioning.py --endpoint a10wed1626vai6-ats.iot.ap-northeast-1.amazonaws.com --root-ca root-CA.crt --cert e4433b0584-certificate.pem.crt --key e4433b0584-private.pem.key --templateName sample-template --templateParameters "{}"

3 DeviceConfigurationの変更

テンプレートを見ると、返却された値は、DeviceConfigurationというキーに格納されていることが分かります。

ここで、この値を 参照値 "Ref":"XXXX" に書き換えて、参照先を Parameters キーに追加します。

Parametersは、デバイス側から送信されるパラメータの型を定義するものですが、この値は、プロビジョニング前のフック(オプション) で実行されるLambdaで上書きが可能です。

Lambdaの戻り値で、parameterOverridesを使用して、これを上書きしているコードです。

Message:default -> Message:Hello!
import json

def lambda_handler(event, context):

    # DISPLAY ALL ATTRIBUTES SENT FROM DEVICE
    print("Received event: " + json.dumps(event, indent=2))

    # ここで有効性のチェックを行う(サンプルのため、常にTrueとしています)
    allowProvisioning = True

    return {
        "allowProvisioning": allowProvisioning,
        "parameterOverrides": {
            "Message": "Hello!"
        }
    }

同じくサンプルで確認すると、指定した情報が返されていることが確認できます。

4 Lambdaによる初期化

プロビジョニングテンプレートでは、証明書の生成・登録と同時に、モノを作成したりタイプを設定することも可能です。

しかし、プロビジョニング前のフック(オプション) で指定されたLambdaでは、生成される証明書の名前(SHA-256ハッシュ)が受け取れるので、その情報を使用して、Thing作成や紐付け、また、関連するShadowやパーミッションの初期化など、きめ細かい初期化処理が可能だと思います。

5 最後に

確認できたように、デバイスの初回接続時にLambda側から任意の情報を返すことは可能です。

証明書を発行するだけでなく、このLambdaを起点にしてデバイスの初期化処理を一気に片付けてしまうのも有りかなと思いました。