S3のバケットポリシー書き方まとめ


最近AWSを勉強し始めたのですが、ポリシーを書くときに毎度迷子になるので
バケットポリシーを中心としてリソースベースのポリシーの書き方をまとめておきます。

## 前提
例えばS3を静的ホスティング先として設定する場合、
・ブロックパブリックアクセスのブロック無効化
・静的ウェブサイトホスティングの有効化
これらを行いますが、それだけだとエンドポイントにアクセスすることはできません。

![スクリーンショット 2021-05-15 17.50.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441432/d5da5858-5bfe-5fc5-bd71-9cfdf6eb5e5e.png)
↑アクセスするとこうなる

何が足りないかというと、**バケットポリシー** の設定です。
S3のバケットポリシーはデフォルトでは全拒否となっています。

## バケットポリシー全貌

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1621068192000",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::${ここにバケットの名前を入れる}"
        }
    ]
}
```
上記のように記述します。

各項目については、 [こちらの公式リファレンスで確認ができます。](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements.html)




### Version
これは**IAMポリシーの文法のバージョン**です。
現在（2021/5/15）は `2012-10-17` です。
もう随分長いこと変わっていませんね。

### Statement.Sid
これはポリシードキュメントに対して**任意で与える識別子**です。ステートメント毎に割り当てることができ、ポリシー内で重複してはいけません。

### Statement.Effect
**許可の一覧であるAllow（ホワイトリスト）にするのか、禁止一覧であるDeny(ブラックリスト)にするのか**を選べます。

### Statement.Principal
**どの相手(Principal)に対して**許可ないし拒否するかを指定します。
指定できる代表的なプリンシパルは下記にのようなものがあります。

- AWSアカウント/ルートユーザー
- IAMユーザー
- IAMロール
- AWSサービス

```
"Principal": { "AWS": "arn:aws:iam::AWSアカウントID:user/userネーム" }
// 下記だと全てのユーザーに対して許可となる
"Principal": { "AWS": "*" }
```

### Statement.Action
許可ないし拒否する**アクション**を指定します。

```
// s3全てのアクション
"Action": "s3:*"
// sqsのsedMessageアクション
"Action": "sqs:SendMessage"
```

### Statement. Resource
一連のステートメントを**どのリソースに反映するか**を記述します。

```
// examplebucketという名前のs3に対してポリシーのステートメントが反映される。
"Resource": "arn:aws:s3:::examplebucket"

// ワイルドカードも一部使用可能。下記はexamplebucketという名前のS3バケット内の全ての項目に対して反映される。
"Resource": "arn:aws:s3:::examplebucket/*"
```

## 応用的な記述
`Condition` を使用して、**ポリシーの実行するタイミングの条件**を指定することができます。
これによって、
- IP制限
- ユーザー名による制限
- HTTP Refererの制限
- MFAの要求
など細かいコントロールをすることができます。

```
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "IPAllow",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
	 "arn:aws:s3:::DOC-EXAMPLE-BUCKET",
         "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"
      ],
      "Condition": {
	 "NotIpAddress": {"aws:SourceIp": "54.240.143.0/24"}
      }
    }
  ]
}
```
上記は Effectが`Deny`(拒否)で `NotIpAddress`としてIPアドレスが指定されているので、
`54.240.143.0/24`のIPアドレス以外は拒否する、という設定になります。

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET",
            "Condition": {
                "StringEquals": {
                    "aws:username": "myname"
                }
            }
        }
    ]
}
```

上記はAWSユーザー名が `myname`の時のみ許可されます。
`aws:username`などのポリシードキュメントで取得できるキーは、下記の公式ドキュメントに一覧があります。
タグやリージョン、日付など、色々なキーが取得できるようです。
[AWS グローバル条件コンテキストキー](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_condition-keys.html)


## ポリシージェネレーター
公式側で[ポリシーのジェネレーター](https://awspolicygen.s3.amazonaws.com/policygen.html)なるものも用意されており非常に便利です。
![スクリーンショット 2021-05-16 13.08.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441432/b2aa4fc8-f8a7-0cba-6e8e-dc037f3a71a3.png)

土台をジェネレーターでサクッと作成し、細かい部分は修正していくといった利用をしていこうと思います。


## 参考資料
- [AWS公式リファレンス](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements_resource.html)
- [S3バケットポリシーの具体例で学ぶAWSのPolicyドキュメント](https://dev.classmethod.jp/articles/learn-aws-policy-documents-with-examples/)
- [IAMについて今更学ぶ](https://qiita.com/qiita-kurara/items/b6123be16fbbc82bfee6)