IoT Coreの証明書を使ってAWSのサービスを利用するための認証情報(アクセスキーIDとシークレットアクセスキー)を発行することができます。
IAMポリシーとうまく組み合わせることで、モノの名前のフォルダー配下だけにアクセスができる構成とすることができます。
設定ファイルをおいてみたりすると実用的ではないでしょうか。
S3
└バケット
├デバイス001 ←他のデバイスのフォルダーは見れない
│ └settiong.json
├デバイス002 ←自分のフォルダーは見れる
│ └settiong.json
├デバイス003
│ └settiong.json
└デバイス004
└settiong.json
参考サイト
- https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/authorizing-direct-aws.html
- https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/example-policies-s3.html
手順は結構長いですが、必要なリソースは以下のとおりです。
サービス | 項目 | 内容 |
---|---|---|
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ファイルを作成します。
{
"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ロールの作成
信頼関係のポリシードキュメントを作成します。
{
"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 ポリシーの作成
{
"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