AWS IoT, AWS IoT Device Shadow

2022.12.04

この記事ではAWS IoT、AWS IoT Device Shadowについて解説します。AWS IoT、AWS IoT Device Shadowを使用することで、簡単にJetson Nanoなどのエッジデバイスをクラウドと連携させることが可能となります。エッジデバイスとクラウドを連携させることで、例えば動的にYOLOv5のモデルをクラウドからエッジデバイスに更新することが可能になります。

以下の操作はAWSアカウントが必要です。

AWS CLIのインストールとセットアップも必要です。

AWS IoT

AWS IoTを使用することで、MQTTという通信プロトコルを使用し、エッジデバイスとクラウドを簡単に接続することが可能となります。

AWS IoTの準備として・モノ、・証明書、・ポリシーを作成し、・モノ証明書をアタッチし・証明書ポリシーをアタッチします。

モノを作成

以下でモノを作成します。以下ではtest-thingという名前のモノを作成します。

aws iot create-thing --thing-name test-thing

証明書を作成し、モノにアタッチ

以下で証明書を作成し、上で作成したモノtest-thingにアタッチします。

$ aws iot create-keys-and-certificate --set-as-active --certificate-pem-outfile certificate.pem --public-key-outfile public.key --private-key-outfile private.key
{
    "certificateArn": "arn:aws:iot:us-east-1:xxxxxxxxxxxx:cert/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    ...
$ aws iot attach-thing-principal --principal arn:aws:iot:us-east-1:xxxxxxxxxxxx:cert/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --thing-name test-thing

aws iot attach-thing-principal--principalで指定するARN(Amazon Resource Name)は、aws iot create-keys-and-certificateで返されたcertificateArnを指定します。

証明書は--certificate-pem-outfileで指定したcertificate.pem、秘密鍵は--private-key-outfileで指定したprivate.keyに作成されます。

ポリシーを作成し、証明書にアタッチ

ポリシーはモノ(正確にはモノにアタッチされた証明書)の通信を制限するための機構で、具体的にはMQTTを使用してデータをパブリッシュ・サブスクライブする際の通信を制限することができます。

cat << EOS > thing-policy.json
{
   "Version": "2012-10-17",
   "Statement": [{
         "Effect": "Allow",
         "Action": "iot:Connect",
         "Resource": "arn:aws:iot:us-east-1:xxxxxxxxxxxx:client/\${iot:Connection.Thing.ThingName}"
      },
      {
         "Effect": "Allow",
         "Action": "iot:Publish",
         "Resource": [
            "arn:aws:iot:us-east-1:xxxxxxxxxxxx:topic/\$aws/things/\${iot:Connection.Thing.ThingName}/shadow/update",
            "arn:aws:iot:us-east-1:xxxxxxxxxxxx:topic/\$aws/things/\${iot:Connection.Thing.ThingName}/shadow/delete",
            "arn:aws:iot:us-east-1:xxxxxxxxxxxx:topic/\$aws/things/\${iot:Connection.Thing.ThingName}/shadow/get"

         ]
      },
      {
         "Effect": "Allow",
         "Action": "iot:Receive",
         "Resource": [
            "arn:aws:iot:us-east-1:xxxxxxxxxxxx:topic/\$aws/things/\${iot:Connection.Thing.ThingName}/shadow/get/*",
            "arn:aws:iot:us-east-1:xxxxxxxxxxxx:topic/\$aws/things/\${iot:Connection.Thing.ThingName}/shadow/update/*",
            "arn:aws:iot:us-east-1:xxxxxxxxxxxx:topic/\$aws/things/\${iot:Connection.Thing.ThingName}/shadow/delete/*"
         ]
      },
      {
         "Effect": "Allow",
         "Action": "iot:Subscribe",
         "Resource": [
            "arn:aws:iot:us-east-1:xxxxxxxxxxxx:topicfilter/\$aws/things/\${iot:Connection.Thing.ThingName}/shadow/get/*",
            "arn:aws:iot:us-east-1:xxxxxxxxxxxx:topicfilter/\$aws/things/\${iot:Connection.Thing.ThingName}/shadow/update/*",
            "arn:aws:iot:us-east-1:xxxxxxxxxxxx:topicfilter/\$aws/things/\${iot:Connection.Thing.ThingName}/shadow/delete/*"

         ]
      },
      {
         "Effect": "Allow",
         "Action": [
            "iot:GetThingShadow",
            "iot:UpdateThingShadow",
            "iot:DeleteThingShadow"
         ],
         "Resource": "arn:aws:iot:us-east-1:xxxxxxxxxxxx:thing/\${iot:Connection.Thing.ThingName}"
      }
   ]
}
EOS
aws iot create-policy --policy-name thing-policy --policy-document file://thing-policy.json
aws iot attach-policy --policy-name thing-policy --target arn:aws:iot:us-east-1:xxxxxxxxxxxx:cert/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

${iot:Connection.Thing.ThingName}はポリシー変数です。このポリシー変数を使用するとモノの名前として評価されます。

arn:aws:iot:us-east-1:xxxxxxxxxxxxの部分は自身のアカウントIDに置き換えて下さい。アカウントIDは以下で取得可能です。

aws sts get-caller-identity|jq -r .Account

またaws iot attach-policy --policy-name thing-policy --targetで指定する、arn:aws:iot:us-east-1:xxxxxxx...aws iot attach-thing-principal--principalで使用したcertificateArnを指定します。

注意点として以下のようなポリシーを使用してしまうと、このポリシーがアタッチされたモノはすべてのリソース(MQTTトピック)に対してパブリッシュ・サブスクライブすることが可能になります。これは別のモノへトピックをパブリッシュ(送信)することや、別のモノへのトピックをサブスクライブ(受信)することが可能になりますので一般的には危険で設定してはいけません。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
         "iot:Publish",
         "iot:Subscribe",
         "iot:Receive"
      ],
      "Resource": ["*"],
    },
  ]
}

AWS IoT Device Shadow

AWS IoT Device SDK v2 for Pythonを使用してAWS IoT Device Shadowの動作を確認します。

$ python3 -m pip install awsiotsdk
$ git clone https://github.com/aws/aws-iot-device-sdk-python-v2.git
$ curl -o AmazonRootCA1.pem https://www.amazontrust.com/repository/AmazonRootCA1.pem

aws-iot-device-sdk-python-v2/samples/shadow.pyを実行します。aws-iot-device-sdk-python-v2/samples/shadow.pyで指定するendpointaws iot describe-endpoint --endpoint-type iot:Data-ATSにより取得します。

$ aws iot describe-endpoint --endpoint-type iot:Data-ATS
{
    "endpointAddress": "xxxxxxxxxxxxxx-ats.iot.us-east-1.amazonaws.com"
}
$ python3 aws-iot-device-sdk-python-v2/samples/shadow.py --endpoint xxxxxxxxxxxxxx-ats.iot.us-east-1.amazonaws.com --key private.key --cert certificate.pem --client_id test-thing --ca_file AmazonRootCA1.pem --thing_name test-thing
Connecting to xxxxxxxxxxxxxx-ats.iot.us-east-1.amazonaws.com with client ID 'test-thing-jetson'...
Connected!
Subscribing to Update responses...
Subscribing to Get responses...
Subscribing to Delta events...
Requesting current shadow state...
Launching thread to read user input...
Thing has no shadow document. Creating with defaults...
Changed local shadow value to 'off'.
Updating reported shadow value to 'off'...
Update request published.
Finished updating reported shadow value to 'off'.
Enter desired value:

shadow.pyは以下のような機能を実現するためのサンプルです。

shadow.pyで使用されるAWS IoT Device Shadowはクラウドとエッジデバイスで共有される以下のJSON形式のデータを持ちます。

{
  "state": {
    "desired": {
      "color": "red",
    },
    "reported": {
      "color": "blue"
    },
    "delta": {
      "color": "red",
    }
  },
  "version": 1,
  "timestamp": 1669898853
}

サンプルshadow.pyを実際の製品として実装する際、照明の色の更新は以下の流れで行われます。

IoT Device Shadowで重要なポイントは以下の通りです。

old desired should be discarded

エッジデバイスとクラウドとの接続は別の記事で解説します。

以上です。

参照

AWS IoT Device Shadow サービス - AWS IoT Core AWS IoT のシャドウ (状態情報を保存および取得するために使用される JSON ドキュメント) とこれらのドキュメントが保存される Device Shadow サービスについて説明します。 docs.aws.amazon.com

GitHub - aws/aws-iot-device-sdk-python-v2: Next generation AWS IoT Client SDK for Python using the AWS Common Runtime Next generation AWS IoT Client SDK for Python using the AWS Common Runtime - aws/aws-iot-device-sdk-python-v2 github.com

[AWS IoT] ポリシー変数で複数のモノをセキュアに管理してみた | DevelopersIO dev.classmethod.jp