AWS IoT – Authorizing Direct Call

2022.12.24

AWS IoTを使用してエッジデバイスからAWSのリソース、例えばAWS S3にアクセスしたくなることがあります。エッジデバイスからS3にアクセスする方法としていくつかありますが、この記事ではAuthorizing Direct Callという仕組みを使用してAWSリソースにアクセスします。

この記事は、こちらの記事で作成したモノ・証明書を使用するため事前に準備を済ませて下さい。

Authorizing Direct Calls

エッジデバイスからAWS S3にアクセスする為に、AWS S3のアクセスを公開設定にしてしまえばエッジデバイスを含む誰からもアクセス可能ですが、公開設定にせず、管理するデバイスからのアクセスを可能とする為に、Authorizing Direct Callsという仕組みを使用します。

AWS S3へのアクセスを可能にする別の方法として、AWS S3の署名付きURLを使用することもできますが、署名付きURLは有効期限があるため目的に応じて使い分けます。

https://docs.aws.amazon.com/iot/latest/developerguide/authorizing-direct-aws.html

Authorizing Direct Callsを利用するために以下の設定を行います。

IoTデバイスに直接IAMロール権限を付与できないため、IoTロールエイリアスを経由し、IAMロール権限を取得します。それぞれの関係は以下の通りです。

IAMロールの作成

IAMロールrole-s3-readを作成します。

$ cat << EOS > role-s3-read.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "credentials.iot.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOS
$ aws iam create-role --role-name role-s3-read --assume-role-policy-document file://role-s3-read.json

IAMポリシーの作成

IAMポリシーpolicy-s3-readを作成し、IAMロールrole-s3-readに設定します。S3バケットxxxxxxxxxx-iot-test-files/以下のファイルを取得可能に設定します。xxxxxxxxxxにはアカウントIDを指定してください。(別の記事でこのバケットを使用するためxxxxxxxxxxはアカウントIDを指定します)

$ cat << EOS > policy-s3-read.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "s3:GetObject"
            ],
            "Effect": "Allow",
            "Resource": "arn:aws:s3:::xxxxxxxxxx-iot-test-files/*"
        }
    ]
}
EOS
$ aws iam put-role-policy --policy-name policy-s3-read --role-name role-s3-read --policy-document file://policy-s3-read.json

IoTロールエイリアスの作成

IoTロールエイリアスiot-role-alias-s3-readを作成し、IAMロールrole-s3-readと紐づけします。

aws iot create-role-alias --role-alias iot-role-alias-s3-read --role-arn arn:aws:iam::xxxxxxxxxxxx:role/role-s3-read

arn:aws:iam::xxxxxxxxxxxx:role/role-s3-readは適切なアカウントIDに置き換えます。アカウントIDは以下で取得可能です。

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

IoTポリシーの作成

IoTポリシーiot-policy-s3-readを作成

$ cat << EOS > iot-policy-s3-read.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iot:AssumeRoleWithCertificate",
      "Resource": "arn:aws:iot:us-east-1:xxxxxxxxxxxx:rolealias/iot-role-alias-s3-read"
    }
  ]
}
EOS
$ aws iot create-policy --policy-name iot-policy-s3-read --policy-document file://iot-policy-s3-read.json

arn:aws:iot:us-east-1:xxxxxxxxxxxxは適切なアカウントIDに置き換えて下さい。

IoT証明書にIoTポリシーをアタッチ

IoT証明書にIoTポリシーiot-policy-s3-readをアタッチします。--target arn:aws:iot:us-east-1:xxxxxxxxxxxxx:cert/xxxxxxxxxxxxxこちらの記事で作成した証明書のARNです。

aws iot attach-policy --policy-name iot-policy-s3-read --target arn:aws:iot:us-east-1:xxxxxxxxxxxxx:cert/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

動作確認

まずはクレデンシャルプロバイダーのエンドポイントを調べます。

$ aws iot describe-endpoint --endpoint-type iot:CredentialProvider
{
    "endpointAddress": "xxxxx.credentials.iot.us-east-1.amazonaws.com"
}

取得したクレデンシャルプロバイダーからトークンを取得します。

$ curl --cert ./certificate.pem --key ./private.key -H "x-amzn-iot-thingname: test-thing" https://xxxxxxxxxxxx.credentials.iot.us-east-1.amazonaws.com/role-aliases/iot-role-alias-s3-read/credentials | jq -r .
{
  "credentials": {
    "accessKeyId": "ASXXXXXXXXXXXXXXXX",
    "secretAccessKey": "otXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "sessionToken": "IQXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "expiration": "2022-12-03T14:14:07Z"
  }
}

S3にxxxxxxxxxx-iot-test-filesバケットを作成し、確認用ファイルを保存します。(繰り返しにないりますが、xxxxxxxxxxはアカウントIDを指定します)

aws s3 mb s3://xxxxxxxxxx-iot-test-files
echo hoge > hoge.txt
aws s3 cp hoge.txt s3://xxxxxxxxxx-iot-test-files/

取得したトークンを使用してS3からファイルをダウンロードします。

$ AWS_ACCESS_KEY_ID="ASXXXXXXXXXXXXXXXX" \
AWS_SECRET_ACCESS_KEY="otXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
AWS_SESSION_TOKEN="IQXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
aws s3 cp s3://xxxxxxxxxx-iot-test-files/hoge.txt .
download: s3://xxxxxxxxxx-iot-test-files/hoge.txt to ./hoge.txt

S3へのアクセスはs3:GetObjectしか許可していないため、リスト操作ができないことを確認します。

$ AWS_ACCESS_KEY_ID="ASXXXXXXXXXXXXXXXX" \
AWS_SECRET_ACCESS_KEY="otXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
AWS_SESSION_TOKEN="IQXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
aws s3 ls s3://xxxxxxxxxx-iot-test-files/hoge.txt

An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied

正しく動作していそうです。

以上です。

参照

AWS IoT Core認証情報プロバイダーを使用して、AWSサービスの直接呼出しを認証 - AWS IoT Core デバイスは、AWS IoT CoreTLS 相互認証プロトコル使用に接続するための X.509 証明書を使用することができます。他の AWS サービスは証明書ベースの認証をサポートしていませんが、 AWS 署名バージョン 4 形式 の AWS 認証情報を使用して呼び出すことができます。 証明書バージョン 4 アルゴリズ… docs.aws.amazon.com

[AWS IoT] 既存の証明書だけでMQTT以外の各種AWSリソ−スにアクセスする (Authorizing Direct Calls) | DevelopersIO AWS IoT の Authorizing Direct Callsを使用すると、既存の証明書だけで、AWSリソースにアクセスする事が可能です。 dev.classmethod.jp