【S3】バケットへのアクセスがタグベースで制御できるようになったので見てみよう
はじめに
データ事業本部の川中子(かわなご)です。
最近S3で属性ベースのアクセス制御(ABAC)がサポートされるアップデートがありました。
S3における以前までのタグベースアクセス制御の方法を振り返りながら、
今回新しくサポートされたS3のABACについて検証してみようと思います。
アップデート概要
今回のアップデートの主な変更点は以下の通りです。
- S3バケット側で
ABAC ステータスを有効化する設定が追加 - ABACを有効化した場合、バケット単位でタグベースの制御が可能に

このアップデートにより、S3バケットに対してタグベースの制御が可能になります。
冒頭のAWS記事では、上記イメージ図①の方法が紹介されていました。
本記事の後半では、2つの方法について検証を行っています。
以前までの方法
以前までS3ではバケット単位のタグベース制御は対応しておらず、
タグベースの制御方法はオブジェクト単位までが制御可能な状態でした。
Amazon S3 supports tag-based authorization for directory buckets, object resources, Amazon S3 Storage Lens, Storage Lens groups, and access points.
オブジェクト単位でタグを管理するのは設定も管理も大変で、
運用には大きな負担が発生するため、あまり現実的な方法ではありませんでした。
この代替手段として、変数${aws:PrincipalTag/Project}でタグ文字列を取得し、
その文字列を含める形でResourceのプレフィックスを指定する方法がありました。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::BUCKET/project/${aws:PrincipalTag/Project}/*"
}
]
}
しかしこの方法では前述の通りバケット単位の制御はできず、
また対象リソースの命名規則の徹底が前提になるため運用上の負担がありました。
今回のアップデートでできること
バケットのABACを有効化すれば、バケット単位でタグベース制御ができるようになり、
ポリシーの設定次第で、ほとんどタグの操作だけでアクセス制御が実現できます。
なお2024年11月にS3バケットのデフォルト作成上限が10,000に引き上げられたので、
規模の大きい組織でも利用用途ごとにバケットを分ける運用は現実的になっています。
検証
冒頭で紹介したイメージ図のように、2つの方法で検証してみました。
方法1:ポリシー内にタグの値を直接記載する方法

AWSブログで紹介されている、ポリシー内でタグの値を直接指定する方法を試してみます。
■ 正常確認
以下の定義で新たにポリシー(s3-abac-policy)を作成します。
accesslvタグの値が3つの値のいずれかであるリソースに対してアクセスを許可します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:ListBucket"
],
"Resource": [
"*"
],
"Condition": {
"StringEquals": {
"aws:ResourceTag/accesslv": [
"public",
"internal",
"confidential"
]
}
}
}
]
}
この条件は対象のタグが付与されているリソースに対する許可なので、
プリンシパル側に対象のタグが付与されていなくてもアクセスが許可されます。
作成したポリシーをロール(cm-kawanago-abac)にアタッチしておきます。
なお前述の通り、このロールにはタグは付与していません。

次に検証用のバケットを作成します。
作成時にaccesslv:confidentialとしてタグを付与しておきます。

作成したバケットのプロパティタブにはバケット ABACの項目が追加されていました。
今回のアップデートによって追加されたようですね。

上記画面の編集ボタンから、ABAC ステータスを有効にするに設定します。
黄色枠で表示される内容を確認し、チェックを入れたら変更を保存します。

cm-kawanago-abacにスイッチロールした状態で、バケットを見てみます。
問題なくバケット内のオブジェクトを閲覧できました。

■ 異常確認
本当にABACが効いているのか確認するために念のため、
ポリシー内で許可していないstrictをバケット側のタグの値に設定してみます。

再度cm-kawanago-abacにスイッチロールしてみると、権限エラーになりました。

なお値がconfidentialの状態で、ABACの設定を無効化しても同じエラーになりました。
これでABACの有効化と、バケットへのタグ付与によるアクセス制御が確認できました。
■ 権限付与状況の把握
付与したポリシー(アクセス権限)を一覧で確認したい場合には、
対象のポリシー詳細画面からアタッチされたエンティティタブを確認します。

■ この方法の課題
今まで利用できなかったバケット単位のABACが実現できて非常に便利ですが、
この方法だと アクセス制御用のタグが増えるたびにポリシーの作成が必要 になり、
またその 権限を付与したいプリンシパルごとにアタッチの操作も必要 になります。
頻繁にアクセス制御用タグに増減がある場合には、運用負荷が大きくなりそうです。
方法2:ポリシー内でタグ変数を使用する方法

次に変数を利用してポリシー内の条件を定義する方法を試してみます。
この方法は以下のAWSドキュメントの方で紹介されています。
■ 正常確認
StringEquals内で使用している変数${aws:PrincipalTag/accesslv}により、
このポリシーがアタッチされているプリンシパルのaccesslvタグの値を取得できます。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:ListBucket"
],
"Resource": [
"*"
],
"Condition": {
"StringEquals": {
"aws:ResourceTag/accesslv": "${aws:PrincipalTag/accesslv}"
}
}
}
]
}
これによりプリンシパルに付与されているaccesslvタグの値と、
バケットに付与されたaccesslvタグの値が一致した場合にアクセスが許可されます。
方法1ではロールに対してのタグの付与はしていなかったので、
ロールにaccesslv:confidentialとしてタグを付与しておきます。

もちろんバケットのタグも、ロールと同じ設定にしておきます。

cm-kawanago-abacにスイッチロールした状態で、再度バケットを見てみます。
この方法でも問題なくバケット内のオブジェクトが閲覧できました。

なお異常確認については方法1と同様に検証してみましたが、
全く同じ結果だったのでここでは割愛させていただきます。
■ 権限付与状況の把握は難しい
アクセス制御の棚卸しとして、ロールに付与したタグの一覧を確認したいところですが、
現時点ではAWS Resource ExplorerでIAMリソースについてタグ検索が利用できないため、
プリンシパルに付与したタグを一覧化するような操作はできません。
At this time, tags attached to AWS Identity and Access Management (IAM) resources, such as roles or users, can't be used for searching.
現状の代替案としては、IAM関連のAPIを組み合わせる方法があります。
まずはlist-rolesでロールの一覧を取得します。
aws iam list-roles --query "Roles[?contains(RoleName, 'cm-kawanago')].RoleName" --output json
# 出力
[
"cm-kawanago-abac",
"cm-kawanago.ryohei"
]
ロールを指定してlist-role-tagsを実行すれば、付与されたタグの一覧を取得できます。
aws iam list-role-tags --role-name cm-kawanago-abac --output json
# 出力
{
"Tags": [
{
"Key": "accesslv",
"Value": "confidential"
}
]
}
なお上記はCLIで実行していますが、boto3などのSDKでも実行は可能なので、
このようなAPIを利用すれば自動でロールとタグの一覧を作成することはできそうです。
Athenaで見れるテーブルとして管理すれば、運用としては現実的だと思います。
■ ポリシーの運用は大幅に効率化される
アクセス制御に利用するタグを全てStringEquals内のリストとして定義すれば、
1つのポリシーを共通してアタッチしておき、あとはタグの付与によりアクセス制御が可能です。
"Condition": {
"StringEquals": {
"aws:ResourceTag/accesslv": "${aws:PrincipalTag/accesslv}",
"aws:ResourceTag/team": "${aws:PrincipalTag/team}",
"aws:ResourceTag/env": "${aws:PrincipalTag/env}"
}
}
注意事項と活用方法
既存のタグへの影響に注意
ABACを有効化した場合、S3バケットの既存タグも制御の対象になるため、
アクセス制御に使用するタグが既に付与されていないか事前に確認しましょう。
コスト配分タグとしての活用
アクセス制御用に設定したタグは、コスト配分用のタグとしても利用できるため、
部署やチーム単位でのタグ利用は組織にとって大きなメリットになりそうです。
またSCPやIAMのポリシーにより、バケット作成時のタグ付与を強制すれば、
組織内でのコスト管理や、ABACによるアクセス制御の運用が徹底しやすくなります。
さいごに
S3バケットにおけるABACのアップデートを検証してみました。
タグベースでバケット単位のアクセス制御が実現できるのは嬉しいですね。
バケット作成上限の緩和も相まって、利用用途ごとにバケットを分ける運用も広がりそうです。
方法2では権限設定作業の負荷を軽減できる反面、権限の把握に課題がある状態なので、
AWS Resource ExplorerにおけるIAMリソースのタグ検索が実装されることに期待です。
少しでも参考になれば幸いです。
最後まで記事を閲覧頂きありがとうございました。








