Amazon S3に対するアクセスコントロールの種類
S3 に対するアクセスコントールは 3 つあり、それぞれの評価論理を考慮しながら使用する必要がありました。
ACL 無効が推奨となった
2021年10月30日より、バケットに対してアクセスコントロールリストの無効化ができるようになりました。
これにより、S3 バケット内のすべてのオブジェクトがバケット所有者に所有されるようになり、評価論理がシンプルになりました。
バケットポリシーと IAM ポリシーの評価論理
バケットポリシー | IAM ポリシー | 結果 |
---|---|---|
指定なし | 指定なし | 失敗 |
許可 | 指定なし | 成功 |
指定なし | 許可 | 成功 |
許可 | 許可 | 成功 |
明示的な拒否 | 許可 | 失敗 |
許可 | 明示的な拒否 | 失敗 |
明示的な拒否 | 明示的な拒否 | 失敗 |
IAM ポリシー、バケットポリシーのどちらかが許可しているとアクセスに成功します。
どちらかの許可があっても、明示的な拒否を加えることで失敗します。明示的な拒否は絶対です。
また、制御したい内容によって、どちらのポリシーに記述するかについてを使い分けることも必要です。
バケットポリシーでの制御が適していること
IP アドレスによる制限
特定の IP アドレス以外のアクセスを拒否する場合は、以下のようなバケットポリシーとなります。
{
"Id": "SourceIP",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SourceIP",
"Action": "s3:*",
"Effect": "Deny",
"Resource": [
"arn:aws:s3:::DOC-EXAMPLE-BUCKET",
"arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"
],
"Condition": {
"NotIpAddress": {
"aws:SourceIp": [
"11.11.11.11/32",
"22.22.22.22/32"
]
}
},
"Principal": "*"
}
]
}
なお、IAM ユーザー/ロール のポリシーに IP アドレス制限をかけることも考えられますが、バケットポリシーに IP アドレス制限を付与しない場合、Administorator などの権限を持った IAM リソースからアクセスができてしまうため、ご注意ください。
これに加えて、IAM ユーザー/ロール でアクセスする場合は、アクセス許可を明示的に追加する必要があります。
参考ドキュメント:Amazon S3 バケットへのアクセスを特定の IP または VPC に制限する
CloudFront のオリジンアクセスアイデンティティ
特定の CloudFront からの読み取りを許可する場合、バケットポリシーは下記となります。
{
"Version": "2012-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity EH1HDMB1FH2TC"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"
}
]
}
参考ドキュメント:オリジンアクセスアイデンティティ (OAI) を使用して Amazon S3 コンテンツへのアクセスを制限する - Amazon CloudFront
特定のサービスからのアクセス許可(例:CloudWatch Logs から S3 バケットへのエクスポート)
S3 バケットにログを出力するケースがあります。その場合、S3 バケットにログを出力する際に用いる AWS サービスに対して許可を与える必要があります。
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "s3:GetBucketAcl",
"Effect": "Allow",
"Resource": "arn:aws:s3:::my-exported-logs",
"Principal": { "Service": "logs.ap-northeast-1.amazonaws.com" }
},
{
"Action": "s3:PutObject" ,
"Effect": "Allow",
"Resource": "arn:aws:s3:::my-exported-logs/random-string/*",
"Condition": { "StringEquals": { "s3:x-amz-acl": "bucket-owner-full-control" } },
"Principal": { "Service": "logs.ap-northeast-1.amazonaws.com" }
}
]
}
参考ドキュメント:コンソールを使用してログデータを Amazon S3 にエクスポートする - Amazon CloudWatch Logs
AWSのリソースに関わらないアクセス制御(例:パブリックアクセスの許可など)
パブリックアクセスを許可する場合、バケットポリシーは下記となります。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"
]
}
]
}
なお、事前にブロックパブリックアクセスを無効にする必要があります。
参考ドキュメント:ウェブサイトアクセスのアクセス許可の設定 - Amazon Simple Storage Service
IAM ポリシーでの制御が適していること
IAM ユーザー/ロールごとに特定の S3 バケットへのアクセスを制限したい
必要に応じてバケット全体を参照できるポリシー s3:ListAllMyBuckets, s3:GetBucketLocation を付与します。この権限がない場合、マネジメントコンソールでバケット一覧が表示できず、どのバケットも選択できなくなります。
{
"Version":"2012-10-17",
"Statement": [
{
"Sid": "AllowStatementListBuckets",
"Action": ["s3:ListAllMyBuckets", "s3:GetBucketLocation"],
"Effect": "Allow",
"Resource": ["arn:aws:s3:::*"]
}
]
}
次に、バケット単位、または、バケット内で特定のプレフィックス名が付いているオブジェクトに対して、制御を行います。 下記の例は、DOC-EXAMPLE-BUCKET にあるオブジェクトをリストできる権限、media というプレフィックス名が付いているオブジェクトを参照する権限を付与しています。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowStatementListBucket",
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::DOC-EXAMPLE-BUCKET"
],
"Condition": {
"StringEquals": {
"s3:prefix": [
"",
"media"
]
}
}
},
{
"Sid": "AllowStatementListBucketPrefix",
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::DOC-EXAMPLE-BUCKET"
],
"Condition": {
"StringLike": {
"s3:prefix": [
"media/*"
]
}
}
},
{
"Sid": "AllowStatementGetObject",
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::DOC-EXAMPLE-BUCKET/media/*"
]
}
]
}
参考ドキュメント:IAM ユーザーに対し Amazon S3 バケットにあるフォルダーへのアクセス権を付与する
まとめ
- ACL 無効化が推奨になったことにより、評価論理がシンプルになった
- 拒否は絶対
- 制御したい内容によって、どちらのポリシーに記述するかを使い分ける
参考資料
S3のアクセスコントロールが多すぎて訳が解らないので整理してみる | DevelopersIO
Amazon S3 Object Ownership で、S3 内のデータのアクセス管理をシンプル化するためのアクセスコントロールリストの無効化が可能に