LoginSignup
6
2

More than 3 years have passed since last update.

AWS IoT Coreの証明書を使ってS3にファイルをアップロードする

Last updated at Posted at 2021-03-30

IoT Coreの証明書を使ってAWSのサービスを利用するための認証情報(アクセスキーIDとシークレットアクセスキー)を発行することができます。
IAMポリシーとうまく組み合わせることで、モノの名前のフォルダー配下だけにアクセスができる構成とすることができます。
設定ファイルをおいてみたりすると実用的ではないでしょうか。

S3
└バケット
  ├デバイス001  ←他のデバイスのフォルダーは見れない
 │ └settiong.json
  ├デバイス002  ←自分のフォルダーは見れる
 │ └settiong.json
  ├デバイス003
 │ └settiong.json
 └デバイス004
   └settiong.json

参考サイト


手順は結構長いですが、必要なリソースは以下のとおりです。

サービス 項目 内容
IoT Core モノ
IoT Core 証明書
IoT Core ポリシー ロールエイリアスに対するiot:AssumeRoleWithCertificateアクションが必要
IoT Core ロールエイリアス 付与したいIAMロールを指定
IAM ポリシー
IAM ロール 信頼関係としてcredentials.iot.amazonaws.comサービスへのsts:AssumeRoleアクションが必要
S3 バケット

こちらの名称で実施しました。

サービス 項目 名称
IoT Core モノ thing-3f21f372
IoT Core 証明書 thing-3f21f372.cert.pem
thing-3f21f372.public.key
thing-3f21f372.private.key
IoT Core ポリシー thing-3f21f372-policy
IoT Core ロールエイリアス s3-bucket-4e8f4765-role-alias
IAM ポリシー s3-bucket-4e8f4765-policy
IAM ロール s3-bucket-4e8f4765-role-for-iot
S3 バケット bucket-4e8f4765

リソース作成

S3

バケットの作成

aws s3api create-bucket \
  --bucket bucket-4e8f4765 \
  --region ap-northeast-1 \
  --create-bucket-configuration LocationConstraint=ap-northeast-1

IAM

IAMポリシーの作成

ポリシー変数の${credentials-iot:ThingName}が、IoTのモノの名前になります。
使えるポリシー変数はこちら。

ポリシー変数
credentials-iot:ThingName
credentials-iot:ThingTypeName
credentials-iot:AwsCertificateId

IAMポリシーのJSONファイルを作成します。

s3-bucket-4e8f4765-policy-document.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::bucket-4e8f4765",
            "Condition": {
                "StringLike": {
                    "s3:prefix": "${credentials-iot:ThingName}/*"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action":[
                "s3:PutObject",
                "s3:GetObject",
                "s3:GetObjectVersion",
                "s3:DeleteObject",
                "s3:DeleteObjectVersion"
            ],
            "Resource": "arn:aws:s3:::bucket-4e8f4765/${credentials-iot:ThingName}/*"
        }
    ]
}
aws iam create-policy \
  --policy-name s3-bucket-4e8f4765-policy \
  --policy-document file://s3-bucket-4e8f4765-policy-document.json

IAMロールの作成

信頼関係のポリシードキュメントを作成します。

s3-bucket-4e8f4765-role-for-iot-policy-document.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "credentials.iot.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
aws iam create-role \
  --role-name s3-bucket-4e8f4765-role-for-iot \
  --assume-role-policy-document file://s3-bucket-4e8f4765-role-for-iot-policy-document.json

IAMポリシーをIAMロールにアタッチ

IAMポリシーをIAMロールにアタッチ
(999999999999はアカウントIDです)

aws iam attach-role-policy \
  --role-name s3-bucket-4e8f4765-role-for-iot \
  --policy-arn arn:aws:iam::999999999999:policy/s3-bucket-4e8f4765-policy

IoT Core

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

IAMロールに対するエイリアスを作成
(999999999999はアカウントIDです)

aws iot create-role-alias \
  --role-alias s3-bucket-4e8f4765-role-alias \
  --role-arn arn:aws:iam::999999999999:role/s3-bucket-4e8f4765-role-for-iot

モノの作成

aws iot create-thing --thing-name thing-3f21f372

証明書の作成

aws iot create-keys-and-certificate \
  --certificate-pem-outfile "thing-3f21f372.cert.pem" \
  --public-key-outfile "thing-3f21f372.public.key" \
  --private-key-outfile "thing-3f21f372.private.key" \
  --set-as-active

AWS IoT Core ポリシーの作成

thing-3f21f372-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iot:AssumeRoleWithCertificate",
      "Resource": "arn:aws:iot:ap-northeast-1:999999999999:rolealias/s3-bucket-4e8f4765-role-alias"
    }
  ]
}
aws iot create-policy \
  --policy-name thing-3f21f372-policy \
  --policy-document file://thing-3f21f372-policy.json

証明書にAWS IoT Core ポリシーのアタッチ

aws iot attach-policy \
  --policy-name thing-3f21f372-policy \
  --target "arn:aws:iot:ap-northeast-1:999999999999:cert/5c3453ecc18e5e6b8f3cf89a6c1d68f62a5b08855d13c61b37c987e3442f70f5"

モノに証明書をアタッチ

aws iot attach-thing-principal \
  --thing-name thing-3f21f372 \
  --principal arn:aws:iot:ap-northeast-1:999999999999:cert/5c3453ecc18e5e6b8f3cf89a6c1d68f62a5b08855d13c61b37c987e3442f70f5

リソースの準備は以上です。

認証情報の取得方法

認証情報の取得は、SDKではなく、curlコマンドで行います。(curl以外でももちろん可能です)

エンドポイントの取得

使用するエンドポイントはアカウントごとに異なります。
あとで使うので環境変数に入れておきます。

export endpoint=`aws iot describe-endpoint --endpoint-type iot:CredentialProvider | jq .endpointAddress | tr -d '"'`

認証情報の取得

以下のパラメーターでリクエストを送信します。

パラメータ 設定値
--cert 証明書ファイル
--key プライベートキー
x-amzn-iot-thingname モノの名称。
これだけHTTPヘッダーで指定です
curl --cert ./thing-3f21f372.cert.pem \
  --key ./thing-3f21f372.private.key \
  -H "x-amzn-iot-thingname: thing-3f21f372" \
  https://${endpoint}/role-aliases/s3-bucket-4e8f4765-role-alias/credentials
結果
{
  "credentials": {
    "accessKeyId": "ASIA3.....",
    "secretAccessKey": "fjKhv..........",
    "sessionToken": "IQoJb.....",
    "expiration": "YYYY-MM-DDThh:mm:ssZ"
  }
}

S3へのアクセス

認証情報を環境変数にセット

認証情報を環境変数にセットします。

credentials=`curl --cert ./thing-3f21f372.cert.pem \
  --key ./thing-3f21f372.private.key \
  -H "x-amzn-iot-thingname: thing-3f21f372" \
  https://${endpoint}/role-aliases/s3-bucket-4e8f4765-role-alias/credentials`

export AWS_ACCESS_KEY_ID=`echo $credentials | jq .credentials.accessKeyId | tr -d '"'`
export AWS_SECRET_ACCESS_KEY=`echo $credentials | jq .credentials.secretAccessKey | tr -d '"'`
export AWS_SESSION_TOKEN=`echo $credentials | jq .credentials.sessionToken | tr -d '"'`

S3にアップロード

[cloudshell-user@ip-10-0-129-6 ~]$ aws s3 cp test.txt s3://bucket-4e8f4765/thing-3f21f372/test.txt
upload: ./test.txt to s3://bucket-4e8f4765/thing-3f21f372/test.txt

無事アップロードできました。

ファイルのリスト取得

[cloudshell-user@ip-10-0-129-6 ~]$ aws s3 ls s3://bucket-4e8f4765/thing-3f21f372/
2021-03-28 06:42:12          5 test.txt

他のフォルダーへのアクセスできないことを確認

自分のフォルダー以外はアクセスできません

[cloudshell-user@ip-10-0-129-6 ~]$ aws s3 ls s3://bucket-4e8f4765/thing-xxxxxxxx/

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

バケット直下もアクセスできないことを確認

[cloudshell-user@ip-10-0-129-6 ~]$ aws s3 cp test.txt s3://bucket-4e8f4765/test.txt
upload failed: ./test.txt to s3://bucket-4e8f4765/test.txt An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2