S3のアクセスコントロール

S3のアクセスコントロールが難解なので再勉強したときの自分用メモ

[（参考）何が嬉しい？S3 Object ACL無効化 - 聞いた後、速攻で忘れていい知識をお届けします \-](https://speakerdeck.com/takashi_toyosaki/he-gaxi-sii-s3-object-aclwu-xiao-hua-wen-itahou-su-gong-dewang-reteiizhi-shi-woojie-kesimasu)
[（参考）S3のアクセスコントロールリスト(ACL)の基礎を学ぼう](https://dev.classmethod.jp/articles/amazon-s3-acl-basics/)
[（参考）S3バケットポリシーの具体例で学ぶAWSのPolicyドキュメント](https://dev.classmethod.jp/articles/learn-aws-policy-documents-with-examples/)
[（参考）S3のバケットポリシーでハマったので、S3へのアクセスを許可するPrincipalの設定を整理する](https://dev.classmethod.jp/articles/summarize-principal-settings-in-s3-bucket-policy/)
[（参考）【AWS】IAM ユーザーに IP 制限](https://hacknote.jp/archives/43145/)
[（参考）【影響調査】S3のパブリックアクセスブロック設定をまとめてみた。](https://furutimes.com/s3-blockpublicaccess/)

---

# 前提
- S3は長いサービスの中で様々なアクセス制御が乱立している
    - ACLとポリシーがあり、それぞれ数種類ある
        - どれかの制御で許可していると公開されていた
    - バケットとオブジェクトで所有者が異なる
        - オブジェクトの所有者の許可がないとバケット所有者であっても  
        自身のバケット内のオブジェクトにアクセスできない
- 意図しない公開を防ぐためにACLとポリシーの変更時にチェックできるようになった
    - 公開範囲を絞らずにポリシーを設定しようとすると拒否される
- 近年はシンプルに制御するようにアクセス制御の機能を制限する動きになっている
    - ACLの無効化
        - オブジェクトの所有者によるアクセス制御は行えない
        - バケットのアクセス制御はポリシーを利用して行う
- よほどの要件ではない限りACLを使うことはない
    - バケットにアップロードされたオブジェクトをバケット所有者に管理されたくない等

# ブロックパブリックアクセス (バケット設定)
![016.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242897/c0e3e4f2-15ec-5000-43f3-f31992ddc5e8.png)

- 全員公開の状態にならないように現状の設定を無効化する（任意の～）
    - ACLの設定で全員公開に設定されている場合は無効にする
    - バケットポリシーの設定でアクセス元を絞り込む条件が記述されていない場合は  
    外部からアクセスできないようにする
        - 同一AWSアカウント内のリソースからのアクセスは制限されない
- 非公開の設定から全員公開の設定に変更できないようにする（新しい～）
    - ACLの設定で全員公開に設定変更できないようにする
    - バケットポリシーの設定でアクセス元を絞り込む条件が記述されていない場合は  
    設定変更できないようにする
    - ACLもバケットポリシーも編集は可能
        - パブリックに公開してしまうような編集をして保存しようとしたときに拒否される
- すべてオンにすることで既存、新規ともに非公開の状態を保つことができる


## 設定時のアクセス検証

| No. |ブロックパブリック <br> アクセス  |バケットポリシー  |アクセス可能範囲  |
|:-:|:-:|:-:|:-:|
|1  |オン  |公開範囲の <br> 絞り込み**あり**  |バケットポリシーは**有効** <br> 公開範囲内はアクセス可  |
|2  |オン  |公開範囲の <br> 絞り込み**なし**  |バケットポリシーは**無効** <br> 同一アカウント内はアクセス可 |
|3  |オフ  |公開範囲の <br> 絞り込み**あり**  |バケットポリシーは**有効** <br> 公開範囲内はアクセス可  |
|4  |オフ  |公開範囲の <br> 絞り込み**なし**  |バケットポリシーは**有効** <br> 全員アクセス可  |

### No.4からブロックパブリックアクセスをオン（No.2）にした場合
- バケットポリシーの記述に変更はなし
    - 同じ内容でバケットポリシーの変更の保存をしようとすると拒否される
- ブラウザからのアクセスは拒否されるようになる
- 同一アカウント内からのアクセスは可能な状態は変わらず


# オブジェクト所有者
![020.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242897/1d029280-5d11-c3c7-e85d-14d0bd4c1eff.png)

- ACLを無効化する
    - オブジェクトの所有者はバケットの所有者となる
- コンソール上ではバケットとオブジェクトのACL編集ボタンはともに非活性になる



# バケットポリシー
![021.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242897/c1a55435-72c7-e8da-cfa7-bd9de50d457c.png)

- ACLを無効化している場合、バケットポリシーかIAMポリシーを利用してアクセス制御する
- どちらかで許可すればアクセスできる
    - IAMポリシーにてS3へアクセスを許可
    - バケットポリシーにてIAMが付与されたリソースからアクセスを許可
- 別のAWSアカウントからS3へのアクセスを許可する場合は両方の許可が必要
    - 別のAWSアカウントのIAMポリシーにてS3へアクセスを許可
    - 自身のAWSアカウントのバケットポリシーにて別のAWSアカウントからアクセスを許可
- 「このバケットに対してブロックパブリックアクセス設定が有効になっているため、  
パブリックアクセスはブロックされています」
    - この表示が出ていれば、公開範囲を絞っていなくても外部からのアクセスが拒否される
    - 公開範囲を絞っていてバケットポリシーが有効な場合（No.1）でも表示されたまま
    - バケットポリシーが無効になっているかどうか（No.1かNo.2かどうか）は  
    表示だけでは分からない
        - 無効になってる場合、同じ記述のままバケットポリシーを変更しようとしたときに  
        拒否される
        ![022.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242897/647f1e19-4602-43e7-1799-18a79b2c186b.png)
        - 無効になってる場合、ブラウザからのアクセスは拒否されるようになる
        ![023.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242897/ad8b6a97-db33-f058-c30e-e0040d64ec14.png)


## ポリシーの使い分け
- 特定のリソースに対して許可するならIAMポリシー
- 不特定の場所に対して許可するならバケットポリシー
- どちらを使っても同じように制御できる場合もある

### バケットポリシー
- バケット単位で付与
- IAMユーザーをもっていなくてもアクセスを許可できる
- 利用シーン
    - 静的ファイルを不特定多数に公開したいとき

### IAMポリシー
- IAMユーザーやEC2に対して付与
- アクセスキーを持っている人やモノにアクセスを許可できる
- 利用シーン
    - 機密情報を人やモノに限定的に公開したいとき

### リソースと場所の両方を満たす場合の許可（同一アカウント内）
- 特定の場所からアクセスキーを持っている人、モノにアクセスを許可する
- IAMポリシーかバケットポリシーどちらかを利用する

#### バケットポリシーを利用
##### IAMポリシー
- 権限なし
![024.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242897/453f6d92-a144-eee4-c434-df245b9fcc21.png)


##### バケットポリシー
- IPとユーザーと権限を指定（一覧取得、オブジェクト操作を指定）

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "ForBacket",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::（バケット名）",
            "Condition": {
                "StringEquals": {
                    "aws:SourceIp": "（グローバルIPアドレス）",
                    "aws:username": "（IAMユーザー名）"
                }
            }
        },
        {
            "Sid": "ForObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:DeleteObject"
            ],
            "Resource": "arn:aws:s3:::（バケット名）/*",
            "Condition": {
                "StringEquals": {
                    "aws:SourceIp": "（グローバルIPアドレス）",
                    "aws:username": "（IAMユーザー名）"
                }
            }
        }
    ]
}
```

##### 実行結果は以下（アクセスキーはプロファイル「user1」に設定）

```
[ec2-user@ip-xxx-xx-xx-xx ~]$ aws configure list --profile user1
      Name                    Value             Type    Location
      ----                    -----             ----    --------
   profile                    user1           manual    --profile
access_key     ****************ABCD shared-credentials-file
secret_key     ****************WXYZ shared-credentials-file
    region           ap-northeast-1      config-file    ~/.aws/config
[ec2-user@ip-xxx-xx-xx-xx ~]$ aws s3 ls s3://（バケット名） --profile user1
2022-01-28 14:46:19     117386 escle.png
[ec2-user@ip-xxx-xx-xx-xx ~]$ aws s3 cp s3://（バケット名）/escle.png ./escle2.png --profile user1
download: s3://（バケット名）/escle.png to ./escle2.png
[ec2-user@ip-xxx-xx-xx-xx ~]$ aws s3 cp ./escle2.png s3://（バケット名）/ --profile user1
upload: ./escle2.png to s3://（バケット名）/escle2.png
[ec2-user@ip-xxx-xx-xx-xx ~]$ aws s3 ls s3://（バケット名） --profile user1
2022-01-28 14:46:19     117386 escle.png
2022-01-29 05:08:50     117386 escle2.png
[ec2-user@ip-xxx-xx-xx-xx ~]$ aws s3 rm s3://（バケット名）/escle2.png --profile user1
delete: s3://（バケット名）/escle2.png
[ec2-user@ip-xxx-xx-xx-xx ~]$ aws s3 ls s3://（バケット名） --profile user1
2022-01-28 14:46:19     117386 escle.png
[ec2-user@ip-xxx-xx-xx-xx ~]$
```


#### IAMポリシーを利用
##### IAMポリシー
- 指定したIPから実行できる権限を指定（一覧取得のみ指定）

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::（バケット名）",
            "Condition": {
                "StringEquals": {
                    "aws:SourceIp": "（グローバルIPアドレス）"
                }
            }
        }
    ]
}
```

##### バケットポリシー
- 権限なし
![025.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242897/8ce36ac6-ddda-343f-789a-d87b488dbf7c.png)



##### 実行結果は以下

```
[ec2-user@ip-xxx-xx-xx-xx ~]$ aws s3 ls s3://（バケット名） --profile user1
2022-01-28 14:46:19     117386 escle.png
[ec2-user@ip-xxx-xx-xx-xx ~]$ 
```

# 今後使うことはないが一応調べた
## アクセスコントロールリスト (ACL)
- 被付与者に対し、バケットのアクセス許可を与える
- バケットとオブジェクトで設定するACLが異なる

### 被付与者
- バケット所有者
- 全員
- AWSアカウントをもつ全員
- S3アクセスログを配信するグループ

# 感想
- 今まではなんとなくIMAポリシーで制御していた
    - 今後はバケットポリシーも機会があれば使っていきたい
- ACLは今度は積極的に無効化していきたい