S3の権限をマトリックスで整理する（IAM、バケットポリシー、ブロックパブリックアクセス、ACL、静的ウェブサイトホスティング）

## 最初に結論

S3でアクセス設定には、IAM、バケットポリシー、ブロックパブリックアクセス、ACL、静的ウェブサイトホスティングなどの機能があります。

この記事では特にIAMポリシー、バケットポリシー、ブロックパブリックアクセスを活用する方法を推奨します。これらの方法を採用することで、セキュリティリスクを低減しつつ柔軟なアクセス管理が可能になります。
それぞれの関係性を表にしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429104/9d1ebb50-4181-802a-615c-6533befe68e3.png)
【表の補足】
認証情報ありアクセス：IAMユーザやVPCエンドポイント、CloudFrontのOAC、署名付きURLなど
パブリックアクセス：ブラウザなどからのアクセス、CloudFrontのpublicなど

本記事では、S3の権限の種類を説明して、その後に、権限設定のプラクティスを説明します。権限の種類を既に理解している方は、目次からプラクティスまで飛んでください。

## S3の権限の種類

まずは権限の種類を説明します。その後に、どのように権限を設定するべきか説明していきます。

### IAM側（アイデンティティベースのポリシー）

ユーザや、IAMロールにアタッチするポリシーです。こちらは、イメージしやすいと思います。

```JSON:IAMのポリシー
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::your-bucket-name",
        "arn:aws:s3:::your-bucket-name/*"
      ]
    }
  ]
}
```

権限の利用する側は明確なので、対象のバケットやパスと許可する（or 拒否する）操作を記述します。

余談ですが、　IAMユーザは使わないようにしましょう。AWSはIAM Identity Center（旧AWS SSO）を利用することを推奨しております。

https://aws.amazon.com/jp/blogs/startup/techblog-iam-sso-concept/

### S3側（リソースベースのポリシー）

S3バケットやオブジェクトに設定するポリシーです。
各機能の説明は公式ドキュメントやブログ、chatGPTに任せて、個人的なおすすめを説明します。

| 機能 | おすすめ |
|:-:|:-:|
| バケットポリシー  |  必要に応じて使う |
| ブロックパブリックアクセス  | 有効（オン）にする  |
| ACL  | 使わない方が良い  |
| 静的ウェブサイトホスティング  | 使わない方が良い  |

:::note info
ブロックパブリックアクセスや静的ウェブサイトホスティングは厳密にはリソースベースポリシーではないですが便宜的に含めております。
:::

#### バケットポリシーは必要に応じて使う

大きく2つのケースで利用がおすすめです。

##### 1. 外部アカウントや他サービスからのアクセスを許可したいケース

大きな会社や複数のプロダクトを持っているなど複数のアカウントがあるケースでは、外部アカウントにアクセスを許可したい場合があると思います。

```JSON:外部アカウントにアクセスを許可
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:root"
      },
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::your-bucket-name/*"
    }
  ]
}
```

また、CloudFrontでホスティングする場合など、他サービスからのアクセスを許可したい場合もあると思います。

```JSON:CloudFrontにアクセスを許可（OAC）
{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::your-bucket-name/*"
            "Condition": {
                "StringEquals": {
                    "AWS:SourceArn": "arn:aws:cloudfront::123456789012:distribution/E1XXXXXXXXXXD4"
                }
            }
        }
    ]
}
```

##### 2. きめ細やかなアクセスを許可・拒否したいケース

バケットや特定のパスに個人情報やクレデンシャルなどの機密情報が含まれている場合は、アクセスを拒否するバケットポリシーを設定するのがおすすめです。
特に、ReadOnlyAccessを広く付与しているアカウントでは、機密情報に多くのユーザやロールがアクセスできてしまうため有効です。

#### ブロックパブリックアクセスは有効（オン）にする

有効化しましょう。
パブリックアクセスは認証なしアクセスをイメージしていただくと良いかと思います。

外部やインターネットからのアクセスを許可したい場合は署名付きアクセスやCloudFrontが利用できます。S3のコンテンツをホスティングしたい場合は、CloudFrontを配置しましょう。

費用面・セキュリティ面を犠牲にしてでも、世界中の全員にあなたのS3へアクセスを許可したい場合のみオフにしましょう。

#### ACLは使わない方が良い

ACLは柔軟性に欠け、誤設定が発生しやすいです。例えば、意図せず公開設定にしてしまうリスクがあり、調査やトラブルシューティングにも時間がかかります。バケットポリシーを利用することで、より明確かつ簡単に設定を管理できます。

ACLにはバケット単位ではなく、オブジェクト単位でのアクセス制御をできる特徴がありますが、そんなことをするとあなたの同僚や後輩のエンジニアが各オブジェクトのオブジェクトACLを都度チェックして設定の背景を調査する羽目になります。

どうしても必要な時以外は、利用を控えましょう。

#### 静的ウェブサイトホスティングは使わない方が良い

昔からある機能で、特殊な場合を除き現在は使わない方が良いです。ブロックパブリックアクセスをオフにする必要があります。

基本的には、静的ウェブサイトホスティングではなく、CloudFrontでOrigin Access Control (OAC)によって公開（ホスティング）する方法を利用するのがおすすめです。
こちらの方法であれば、ブロックパブリックアクセスを有効（オン）にした状態で公開できます。

どうしても必要な時以外は、利用を控えましょう。

## S3の権限のプラクティス

まず、ACL、静的ウェブサイトホスティングは使わないようにしましょう。
どうしても必要な場合は、セキュリティ面・費用面・技術的負債面を考慮して判断しましょう。

次に大きく3つの観点で考えましょう。

### 1. ブロックパブリックアクセスを設定する

ブロックパブリックアクセスは有効（オン）にしましょう。
意図しないパブリックアクセスを防ぐことができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429104/eb865ef8-2c2d-232e-345a-b5dfd8b40713.png)

### 2. 権限を許可する


ユーザやロールにはIAMで、外部アカウントや他サービスにはバケットポリシーで権限を付与しましょう。
暗黙的に拒否（設定なし）と許可の場合は、アクセス許可されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429104/37bb5f51-6614-5cb8-1e6f-c5c289faf557.png)


:::note info
暗黙的に拒否とは、DenyもAllowも記述されていない場合にデフォルトで拒否されることを指します。

[明示的な拒否と暗黙的な拒否の違い](
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_evaluation-logic_AccessPolicyLanguage_Interplay.html)

:::


### 3. 権限を拒否する


バケットポリシーで明示的に拒否した場合は、他の設定に関わらず拒否されます。
S3に機密情報が含まれている場合は、設定しましょう。ReadOnlyAccessで見れてしまいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429104/900b1a8c-a08b-28c6-3851-9549962ec5a9.png)

## 最後に

米国IT調査会社のガートナーは「2025年までにクラウドセキュリティインシデントの99%は顧客の過失によるものになる」と予測しております。

https://www.gartner.com/smarterwithgartner/is-the-cloud-secure

本記事によって少しでも、S3からの情報流出リスク減少に貢献できることを願っております。