お願い城之内、Amazon S3 のバケットポリシーに Deny を使わないで!

AWS

2022.11.28

Topics

こんにちは。デュエリストのMr.oldtypeです。
好きなデッキは六武衆と剣闘獣です。よろしくお願いします。

最近、S3バケットのバケットポリシーを誤って設定してしまい、アクセスが出来なくなってしまった。というお問い合わせが非常に増えています。
注意喚起と題して絶対にやってはいけない設定と、オススメ設定についてお話します。

絶対にやってはいけない例

「特定のIPだけ許可して、あとは全てブロックしたい」と思い、以下のようなポリシーを記載しました。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",  ### 許可する
            "Principal": "*",
            "Action": "s3:*",   ### S3の全ての操作を
            "Resource": [
                "arn:aws:s3:::DOC-EXAMPLE-BUCKET",  ### あるバケットと
                "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*" ### あるバケットの中身全部に
            ],
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": "54.240.143.0/24"  ### このIPからのみ
                }
            }
        },
        {
            "Effect": "Deny", ### 拒否する
            "Action": "*", ### 全ての操作を
            "Resource": "*"  ### 全てにおいて
        }
    ]
}

一見ホワイトリスト形式で問題なさそうに思えますが、この設定をバケットポリシーに貼り付けると rootユーザー以外から全ての動作を受け付けなくなります。
バケットポリシーの編集も出来なくなるので、詰みます。
一番問題なのはこいつです。

        {
            "Effect": "Deny", ### 拒否する
            "Action": "*", ### 全ての操作を
            "Resource": "*"  ### 全てにおいて
        }

IAMポリシーも含めAWSにおけるjsonで記述するこういったルールでは、Denyは最強で明示的なAllowより必ず優先されます。
今回の場合は下記のようにするのが正しい用法です。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",   ### 拒否する
            "Principal": "*",
            "Action": "s3:*",   ### S3の全ての操作を
            "Resource": [
                "arn:aws:s3:::DOC-EXAMPLE-BUCKET",    ### あるバケットと
                "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"   ### あるバケットの中身全部に
            ],
            "Condition": {
                "NotIpAddress": {                      ### 以下のIPに当てはまらない場合
                    "aws:SourceIp": "54.240.143.0/24" ### このIP
                }
            }
        }
    ]
}

参考URL:https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/example-bucket-policies.html
ただ上記公式ドキュメントにもありますが、いずれにせよDenyで拒否するポリシーとなりますので、IPアドレスが誤っている場合アクセス不可となりますので非常に注意が必要です。

バケットポリシーとACLの違い

じゃあどうしたらええねん!という話の前に、S3のアクセス制限について簡単におさらいします。
大きく下記の方法があります。

・ バケットポリシーによる制御
・ アクセスコントロールリスト(ACL)による制御
・ アクセスするIAMに対する制御(ユーザーポリシー)

IAMによる制御はS3ではなくアクセスする側で制御する方法なので今回は割愛します。
残るはバケットポリシーとACLなんですが、一部特殊なケースを除いてバケットポリシーのみで十分な制御が出来ます。
(特殊なケース:バケット全体ではなく個々のオブジェクトに対してアクセス制御を行いたい場合)
二種類ある理由はシンプルにバケットポリシーが後から登場した(2010/7/6 – ニュースブログ)ためで、現在ACLは無効化することを推奨されています。
そのため、S3のアクセス制御はバケットポリシーか、ユーザーポリシーで行うと覚えておきましょう。

Denyを使わずに制御するには

少し話がそれましたが、ではDenyを使わずにアクセス制御する方法を考えてみます。
ポイントは暗黙のDenyです。
バケットポリシーでは明示的なAllowのみでポリシーを構成することで、許可されてないものは許可しない=暗黙のDenyが発動します。
先ほどの例を明示的なAllowのみで構成すると下記のようになります。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",   ### 許可する
            "Principal": "*",
            "Action": "s3:*",   ### S3の全ての操作を
            "Resource": [
                "arn:aws:s3:::DOC-EXAMPLE-BUCKET",    ### あるバケットと
                "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"   ### あるバケットの中身全部に
            ],
            "Condition": {
                "IpAddress": {                      ### 以下のIPに当てはまる場合
                    "aws:SourceIp": "54.240.143.0/24" ### このIP
                }
            }
        }
    ]
}

やってることは先に書いたものと同じなのですが、こちらは暗黙のDenyなので、ユーザーポリシーでこのバケットに対するアクセスを持ったユーザーがアクセスすることが可能となります。
ですので万が一、指定するIPアドレスを間違えてしまった場合でも、このバケットに対するアクセス許可を持ったIAMユーザーが居れば修正可能となるのです。
ただ裏返すと「絶対このIPからじゃないとダメ!」という場合は抜け道となってしまうので、難しいかもしれません。
ユースケースに応じてご判断ください。

テックブログ新着情報のほか、AWSやGoogle Cloudに関するお役立ち情報を配信中!

Mr.oldtype

クラウドを楽しくする、をテーマに活動しています。 2021/2022 APN Top Engineer。 でしょうね、ミスター・オールドタイプ。

Recommends

こちらもおすすめ

Special Topics

注目記事はこちら