S3 の ListObjects, ListBucket などについてのあれこれ
S3 を色々触っていて気になる事・ちょっとハマった事などがいくつかあったので、それについて書く。
s3:ListObjects という action は存在しない
S3 API には、ListObjects
という API がある。あるバケットのあるディレクトリ(正確には prefix だけど)配下のオブジェクト一覧を返すというもの。
ListObjects – Amazon Simple Storage Service
で、この操作を特定の人に許可するバケットポリシーを作成しようとして、s3:ListObjects
という action を許可しようとしたら “S3 policy has invalid action” みたいなエラーが出た。
結論からすると、 s3:ListObjects
という action は存在しない。ListObjects
という操作をを許可するためには s3:ListBucket
という action を許可する必要がある。
以下の SO が簡潔にまとまってる。
amazon web services – AWS Bucket Policy Error: Policy has invalid action – Stack Overflow
細かい解説を見たければ、日本語の以下の記事が詳しい。
S3の特定パスのみに対して全ての操作が可能なIAMポリシー | DevelopersIO
S3 の action の一覧などは、以下のページを参照。
Actions, resources, and condition keys for Amazon S3 – Service Authorization Reference
s3:ListBucket と s3:ListAllMyBuckets
前述の通り s3:ListBucket
と言うのは、オブジェクト一覧を閲覧する許可するためのものであり、バケット一覧の閲覧を許可したい場合は s3:ListAllMyBuckets
という action がある。AWS、S3 をある程度使っている人であれば、この名前にモヤモヤしている人も多いと思う。
以下の SO の回答によれば、S3 は AWS 最古参のサービスだから、その辺の名前付けとかがちゃんと決まってない時代の遺産なのでは、という事だった。
amazon web services – Invalid Action: The action s3:ListObjects does not exist – Stack Overflow
ちなみに、 s3:ListBucket
は、”bucket” という単語が単数形なのに注意。ある1つの bucket の中身を一覧表示する、という意味なのが分かると思う。実際には存在しないが s3:ListBuckets
という名前であれば、bucket の一覧を表示する意味だけど。
バケットへの操作とオブジェクトへの操作
S3 の action には、主にバケットへの操作とオブジェクトへの操作の2つに大別される。例えば、s3:ListObject
はバケットへの操作であり、 s3:GetObject
はオブジェクトへの操作である。
良くあるユースケースとして、some_role
に対して example-bucket
というバケットの dir-a
というディレクトリ配下への読み込み権限を付与するという例を考える。この場合、
arn:aws:s3:::example-bucket
に対してs3:ListBucket
を許可arn:aws:s3:::example-bucket/dir-a/*
に対してs3:GetObject
を許可
という形で権限設定を行う事になる。
CloudFormation の設定を抜粋すると以下のような感じになる。
ExampleBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref ExampleBucket
PolicyDocument:
Id: ExampleBucketPolicy
Statement:
- Sid: SomeRoleReadOnly
Effect: Allow
Action:
- s3:GetObject
- s3:ListBucket
Resource:
- "arn:aws:s3:::example-bucket"
- "arn:aws:s3:::example-bucket/dir-a/*"
Principal:
AWS: "arn:aws:iam::1234567890:role/some_role"
ちょっと面白い(分かりづらい)のは 、action として s3:GetObject
と s3:ListBucket
の2つを指定し、resource に arn:aws:s3:::example-bucket
と arn:aws:s3:::example-bucket/dir-a/*
の2つを指定しているが、バケットに対する action (s3:ListBucket
)はバケットに対してのみ適用され、オブジェクトに対する action (s3:GetObject
)はオブジェクトに対してのみ適用されるということ。(当たり前といえば当たり前だけど。)
S3 の action として(主に)バケットへの操作とオブジェクトへの操作の2種類があるということを知らないと、上の CloudFormation の設定を見たときに、
「え? dir-a
以外の読み込みも許可されてしまうんじゃない?」
と思うかもしれない。
まとめ
S3 の権限設定は複雑すぎる。