【ABAC】S3でタグベース制御を行う(制限あり)
S3における ABAC(Attribute-based access control) の実現方法を 2つ紹介します。
[前提] S3のABAC
S3でタグベース制御が可能かどうかは以下ページで分かります。
S3は上図のとおり [部分的※] となっています。この注釈には以下のように書かれています。
Amazon S3 はオブジェクトリソースに対してのみタグベースの認証をサポートしています。
つまり S3バケット単位のタグベース制御はできません 。
[方法1] オブジェクトに対して ABAC
前述の通り S3の「オブジェクト」に対してはタグベース制御が可能です。 以下 2項目を確認してみましょう。
適当な S3オブジェクトにタグを付けています。
aws s3 ls s3://$BUCKET/test.txt # 2021-07-12 08:49:08 5 test.txt aws s3api get-object-tagging --bucket $BUCKET --key test.txt --output yaml # TagSet: # - Key: Project # Value: XXX
各ロールにはタグの値で GetObject の許可を判別するポリシーのみ付与しています。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "s3:GetObject", "Resource": "*", "Condition": { "StringEquals": { "s3:ExistingObjectTag/Project": "${aws:PrincipalTag/Project}" } } } ] }
【確認1】GetObject できること
ロールXには以下のようなタグ付を行っています。
aws iam tag-role --role-name $ROLEX --tags Key=Project,Value=XXX aws iam list-role-tags --role-name $ROLEX --output yaml # IsTruncated: false # Tags: # - Key: Project # Value: XXX
以下のように、GetObject できていること確認できました。
aws --profile role-x s3api get-object --bucket $BUCKET --key test.txt test-from-rolex.txt # AcceptRanges: bytes # ContentLength: 5 # ContentType: text/plain # ETag: '"d8e8fca2dc0f896fd7cb4cb0031ba249"' # LastModified: '2021-07-11T23:49:08+00:00' # Metadata: {} # ServerSideEncryption: AES256 # TagCount: 1 cat test-from-rolex.txt # test
【確認2】GetObject できないこと
ロールYには以下のようなタグ付を行っています。
aws iam tag-role --role-name $ROLEY --tags Key=Project,Value=YYY aws iam list-role-tags --role-name $ROLEY --output yaml # IsTruncated: false # Tags: # - Key: Project # Value: YYY
こちらは GetObject ができません。想定通り Access Denied
となりました。
aws s3api get-object --bucket $BUCKET --key test.txt test-from-roley.txt # An error occurred (AccessDenied) when calling the GetObject operation: Access Denied
[方法2] パスで ABAC
IAMのポリシー変数 を使って、 S3バケットのパス単位でABACが可能 です。 以下 2項目を試してみます。
- プロジェクト
XXX
用のデータ (text-xxx.txt
) - プロジェクト
YYY
用のデータ (text-yyy.txt
)
を以下のようにプレフィクスを分けて保存します。
aws s3 ls s3://$BUCKET/project/XXX/ # 2021-07-13 14:55:33 13 test-xxx.txt aws s3 ls s3://$BUCKET/project/YYY/ # 2021-07-13 14:55:42 13 test-yyy.txt
ロールには タグの値で「アクセスできるリソース」を分ける ようなポリシーをアタッチします。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::BUCKET/project/${aws:PrincipalTag/Project}/*" } ] } # ※ "BUCKET" は対象バケット名
また、ロールへのタグ付けも行います。
aws iam tag-role --role-name $ROLEX --tags Key=Project,Value=XXX aws iam list-role-tags --role-name $ROLEX --output yaml # IsTruncated: false # Tags: # - Key: Project # Value: XXX
【確認1】GetObject できること
/project/XXX/
配下のオブジェクトにはアクセスできます。
aws s3api get-object --bucket $BUCKET \ --key project/XXX/test-xxx.txt test-xxx.txt # AcceptRanges: bytes # ContentLength: 13 # ContentType: text/plain # ETag: '"53d49e003e2cea063e680fc65cddf659"' # LastModified: '2021-07-13T05:55:33+00:00' # Metadata: {} # ServerSideEncryption: AES256 cat test-xxx.txt # test for XXX
【確認2】GetObject できないこと
/project/YYY/
配下のオブジェクトには アクセスできません 。
aws s3api get-object --bucket $BUCKET \ --key project/YYY/test-yyy.txt test-yyy.txt # An error occurred (AccessDenied) when calling the GetObject operation: Access Denied
おわりに
S3のタグベース制御例を紹介しました。 紹介した方法で ABAC が実現できますが、やはり運用管理はちゃんと考える必要があります。 タグによる分類を行う前に、 バケット/アカウントを分離して対応できないか 十分に検討しましょう。
また、 [方法2] パスでABAC
のポリシー変数を活用するところは、
ABACでなくても活用できると思います。
例えば aws:username を使って、
ユーザー単位でアクセスできるパスを制御する活用もアリでしょう。