バケットポリシーに本気なS3標準テンプレートのご紹介

# はじめに
AWSのS3は、オブジェクトストレージサービスとして広く利用されていますが、設定ミスや誤操作によって情報漏洩のリスクにさらされることがあります。この記事では、S3の情報漏洩を防ぐために、リソースベースポリシーを使ったS3標準テンプレートをご紹介します。

[Security-JAWS【第31回】勉強会](https://s-jaws.doorkeeper.jp/events/165371)で発表したセッション、「S3の情報漏洩からデータを守るには？CloudFormationで作るS3標準テンプレートのご紹介」の内容を記事化したものです。

アーカイブ録画

https://youtu.be/BVISc17QYgI?t=5323

セッション資料

https://speakerdeck.com/chiharutsuboi/s3noqing-bao-lou-xie-karadetawoshou-runiha-cloudformationdezuo-rus3biao-zhun-tenpuretonogoshao-jie


# リソースベースポリシーとは
IAMポリシーとして設定できる対象のひとつです。

- アイデンティティベースポリシー
IAMユーザー、IAMグループ、IAMロールにアタッチされ、そのエンティティが行うことができるアクションとアクセスできるリソースを制御する。例えば、特定のIAMユーザーがS3バケットに対してどのような操作を行うことができるかを定義することが可能。

- リソースベースポリシー
リソース自体にアタッチされ、そのリソースに対するアクセスを制御する。リソースベースポリシーは、特定のリソースに対してどのIAMエンティティがどのようなアクションを実行できるかを指定する。S3バケットのリソースベースポリシーは「バケットポリシー」と呼ばれる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2741587/538f5b10-e7b7-b7c6-6afc-3b7ddbda9ae7.png)

# データ境界の確立
リソースベースポリシーはアクセスコントロールにおける重要機能です。
下記はアイデンティティベースポリシーでは実現できません。
- VPCEのリソースベースポリシー（エンドポイントポリシー）で他アカウントへのアクセスを明示拒否によりマルウェアが侵入しても情報の持ち出し不可 

- S3のリソースベースポリシー（バケットポリシー）により、他ネットワークからのアクセス不可 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2741587/66e95315-8205-5a03-7a0f-f199746c0bc5.png)


# S3標準テンプレートとは
S3のセキュリティに関するベストプラクティスを反映したテンプレートで、以下のような機能を提供します。

- リソースベースポリシーを利用したアクセスコントロール
- KMSによる暗号化
- バージョニング／StargeLensの作成

CloudFormationで構成することにより標準化、展開が容易です。
システムの開発開始時に雛型として利用し、セキュリティのベースラインを担保します。


# 主な機能①：アクセスコントロール
リソースベースポリシーによる明確なアクセス制御を行います。

- パブリックアクセスブロック設定
- パラメータにより、VPC Endpoint経由に限定
- アクセス可能なIAMロールを限定

暗黙拒否を利用しない明示的アクセスコントロールを行うようにしています。
- 必要最低限のアクセスを明示的に許可
- それ以外のアクセスを明示的に拒否

これにより、指定が無ければ「AdministratorAccess」ポリシーが付与されたロールも拒否します。
暗黙的拒否だったところにマルウェアが侵入しても許可されることがありません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2741587/cb961dcb-5eb7-949b-5b92-665e33a99c15.png)

# 主な機能②：暗号化の強制
全ての暗号化を強制しKMSの設定もセットで行います

- 暗号化通信の強制
    - HTTPSトランスポートでのみアクセス可能

- 強固な暗号化スイートの強制
    - TLSv1.2以上でのみアクセス可能

- サーバーサイド暗号化の強制
    - AWS KMSキーを使用したサーバーサイド暗号化を適用
    - 暗号キーは下記を選択可能
    	- SSE-KMS(AWS Managed Key)
    	- SSE-KMS(Customer Managed Key)
    - パラメータ有無によりKMSキーもセットで作成
    - KMSのリソースベースポリシー（51アクション）もS3の権限と同様に定義しています


# 主な機能③：バージョニング／StorageLens
バージョニングやStorageLensなどを容易に設定できます

- バージョニング及びバージョンデータのライフサイクル設定可能
- 不完全なマルチパートアップロードの削除がデフォルトで設定済み
- StorageLens（高度なメトリクス）の作成可能
    - 標準：ストレージサイズ、オブジェクト数、等
    - 高度：リクエスト数、エラー数、等


## アクセス可能なIAMロールを限定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2741587/d9e743f0-96e7-36c6-f686-79731f578ca4.png)


- Admin
    - <font color="BLUE"><B>バケット自体に対する管理権限</font>を有する
    - バケット内のオブジェクトは書き込みできない
- Writable
    - バケット内の<font color="BLUE"><B>オブジェクトに対する管理権限</font>を有する
    - バケット自体の設定（バケットポリシー等）は書き込みできない
- ReadOnly
    - オブジェクトの参照専用
    - バケット自体の設定やオブジェクトの書き込みはできない

アプリ（EC2等）は「Writable」とすることで、万が一マルウェアに乗っ取られた場合もバケットポリシーの変更はできず、被害の拡大を防ぐことができます。

## IAMロールによるアクション制限
各ロール権限範囲のアクションを定義します。

- S3のアクションは130種類
- リソースベースポリシーで記載できないアクション49件を除く81件に対し、各ロールに権限を定義

権限一覧（一部を抜粋）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2741587/13b573b2-1298-cd55-fba4-15abc613e771.png)

## バケットポリシー概要
下記のようなポリシーのステートメント構成です。
Not〇〇により想定外アクセスを明示拒否しています。

- 想定外アクセスを全拒否
    - Admin,Writable,Readonlyロール以外(StringNotEquals)の全てのプリンシパルに対して全てのアクションを拒否
- Adminロールに対するポリシー設定
    - 権限を有するアクションを許可
    - 上記以外(NotAction)を拒否
- Writableに対するポリシー設定
    - 権限を有するアクションを許可
    - 上記以外(NotAction)を拒否
- Readonlyに対するポリシー設定
    - 権限を有するアクションを許可
    - 上記以外(NotAction)を拒否

## コード例：想定外アクセスを全拒否
Admin,Writable,Readonlyロール以外(StringNotEquals)の全てのプリンシパルに対して全てのアクションを拒否

```yaml:想定外アクセスを全拒否
# Admin,Writable,Readonlyロール以外の全てのプリンシパルに対して全てのアクションを拒否
- Sid: Deny all actions except Administrative Writable ReadOnly role
  Effect: Deny
  Principal: "*"
  Action:
    - s3:*
  Resource: 
    - !Sub ${StandardBucket.Arn}/*
    - !Sub ${StandardBucket.Arn}
  Condition: 
    StringNotEquals:
      aws:PrincipalARN: 
          !Split [',', !Sub '${AdministrativeRoleArn},${ReadOnlyRoleArn},${WritableRoleArn}']
```

## コード例：Adminロールに対するポリシー設定

```yaml:権限を有する49件のアクションを許可
# Administrativeロールに許可される全アクションを許可
- Sid: Allow actions for Administrative role
  Effect: Allow
  Principal: 
    AWS: !Split [',', !Sub '${AdministrativeRoleArn}']
  Action:
    - s3:BypassGovernanceRetention
    - s3:DeleteBucket
    - s3:DeleteBucketPolicy
    - s3:DeleteBucketWebsite
    - s3:GetAccelerateConfiguration
    # 省略
  Resource: 
    - !Sub ${StandardBucket.Arn}/*
    - !Sub ${StandardBucket.Arn}
```
```yaml:上記以外(NotAction)を拒否
# Administrativeロールに許可されないアクションを拒否
- Sid: Deny actions for Administrative role
  Effect: Deny
  Principal: 
    AWS: !Split [',', !Sub '${AdministrativeRoleArn}']
  NotAction:
    - s3:BypassGovernanceRetention
    - s3:DeleteBucket
    - s3:DeleteBucketPolicy
    - s3:DeleteBucketWebsite
    - s3:GetAccelerateConfiguration
    # 省略
  Resource: 
    - !Sub ${StandardBucket.Arn}/*
    - !Sub ${StandardBucket.Arn}
```

## コード例：Writableロールに対するポリシー設定

```yaml:権限を有する54件のアクションを許可
# Writableロールに許可される全アクションを許可
- Sid: Allow actions for writable role
  Effect: Allow
  Principal: 
    AWS: !Split [',', !Sub '${WritableRoleArn}']
  Action:
    - s3:AbortMultipartUpload
    - s3:DeleteObject
    - s3:DeleteObjectTagging
    - s3:DeleteObjectVersion
    - s3:DeleteObjectVersionTagging
    # 省略
  Resource: 
    - !Sub ${StandardBucket.Arn}/*
    - !Sub ${StandardBucket.Arn}
```
```yaml:上記以外(NotAction)を拒否
# Writableロールに許可されないアクションを拒否
- Sid: Deny actions for writable role
  Effect: Deny
  Principal: 
    AWS: !Split [',', !Sub '${WritableRoleArn}']
  NotAction:
    - s3:AbortMultipartUpload
    - s3:DeleteObject
    - s3:DeleteObjectTagging
    - s3:DeleteObjectVersion
    - s3:DeleteObjectVersionTagging
    # 省略
  Resource: 
    - !Sub ${StandardBucket.Arn}/*
    - !Sub ${StandardBucket.Arn}
```

※ReadOnlyも同様なので割愛




# S3標準テンプレートの課題
まだ作成して間もないですが、下記の課題があります。

- 開発環境での利用しやすさ
    - オブジェクトの一覧表示はAdminにも付与してよいのではないか
    - Readonlyロールは不要なケースもあるので必須ではなくオプション項目に

- 使い初めの学習コスト
    - S3標準テンプレートが900行　→コメントの充実化
    - パラメータが11項目　→必須項目を減らす

- 利用範囲
    - 用途によっては標準テンプレートを採用できない制約がある。
        - 例えばALBのアクセスログの場合はロールを指定できず、SSE-KMSも利用できない
        - この場合は用途専用のテンプレートを用いる方針


# まとめ
データ境界を確立することで情報漏洩のリスクが軽減します。
リソースベースポリシーを活用したS3標準テンプレートのご紹介でした。
セキュリティ対策の参考になれば幸いです。

# 参考サイト
* Security-JAWS【第31回】 勉強会 2023年11月15日(水)
https://s-jaws.doorkeeper.jp/events/165371
* Blog Post Series: Establishing a Data Perimeter on AWS
https://aws.amazon.com/jp/identity/data-perimeters-blog-post-series/