こんにちは!
SREチームマネージャーの藤原です。
今回はライトな話題として、s3:ListBucketのプレフィックス指定で時間を無駄にしたお話をしたいと思います。
よくあるs3リソースへのアクセス用ポリシー
特定のS3バケット内オブジェクトへの書き込み、読み込み、一覧表示としたい場合以下のようなIAMポリシーを作成することがよくあるでしょう。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:ListBucket" ], "Resource": [ "arn:aws:s3:::バケット名", "arn:aws:s3:::バケット名/*" ] } ] }
特定のバケット内のオブジェクト全ての場合はこれで問題ありません。 では、指定したバケットの特定プレフィックスを持つオブジェクトのみを書き込み、読み込み、一覧表示したい場合はどうなるでしょう。
意図した動作をしないパターン
まずは意図したとおり動作せず失敗したパターンです。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:ListBucket" ], "Resource": [ "arn:aws:s3:::バケット名/aaaa/bbbb/*" ] } ] }
一見良さそうに見えます。
オブジェクトのアップロード、ダウンロード共に問題なく、s3:PutObject、s3:GetObjectは意図した通りに動作しています。
一方でAWS CLIを使ってaws s3 ls s3://バケット名/aaaa/bbbb/とすると以下のようなエラーが返ってきます。
An error occurred (AccessDenied) when calling the ListObjectsV2 operation: User: arn:aws:iam::アカウントID:user/IAMユーザー名 is not authorized to perform: s3:ListBucket on resource: "arn:aws:s3:::バケット名" because no identity-based policy allows the s3:ListBucket action
指定したバケットへのs3:ListBucketは認可されてないと言われてしまいます。
原因の特定
原因の特定のために、AWSの公式ドキュメント(Amazon S3 のアクション、リソース、条件キー)を見てみましょう1。
正常に動作しているGetObject、PutObjectを見てみましょう。
Resource typeとしてobjectが必須指定となっています。
オブジェクトのARNはarn:${Partition}:s3:::${BucketName}/${ObjectName}の形で指定します。
ListBucketの行を眺めてみると、Resource typeとしてbucketが必須指定となっています。
バケットのARNの指定例はarn:${Partition}:s3:::${BucketName}となっており、先で失敗した内容ではResourceで指定している内容が適切ではないことになります。
では、ListBucketで特定プレフィックスの配下だけを参照できるようにするにはどうしたら良いでしょう。
再度公式ドキュメントを眺めてみます。
ListBucketでは、Condition keysにs3:prefixが指定できることがわかります。
s3:prefix条件キーを利用することで、キー名のプレフィックスを基にアクセスをフィルタリングすることができます。
最終的な形
s3:ListBucketはリソースとしてバケットを指定しなければならず、プレフィックスでアクセス制限をしたい場合はs3:prefixを条件キーとして指定する必要があることがわかりました。
最終的に指定したバケットの特定プレフィックスを持つオブジェクトのみを書き込み、読み込み、一覧表示するためのポリシーは以下のようになりました。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject" ], "Resource": [ "arn:aws:s3:::バケット名/aaaa/bbbb/*" ] }, { "Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::バケット名", "Condition": { "StringLike": { "s3:prefix": "aaaa/bbbb/*" } } } ] }
トラブルシュートの際は最終的には公式ドキュメントをしっかり読み込むことが重要ですね。
- なお、本エントリで解説している内容は2024年9月時点のドキュメントをもとにしています。将来的には変更されている可能性がある点にはご留意ください。↩