そのS3暗号化ちょっと待って(SSE-S3とSSE-KMSの違いと注意点)

## はじめに
S3で利用する暗号化キーに対する特別な要件が無い PJ の場合、
検討する S3 の暗号化方式は SSE-S3 と SSE-KMS の 2 種類があるかと思います。
なんとなく他サービスでも利用している SSE-KMS を使用していませんか？

同じ暗号化かつ、AWS のマネージドキーなら機能に違いはないため、
どちらでもいいと考えてしまうことがあるかもしれません。
本記事は S3 において SSE-KMS を選んでエラーとなるケースと暗号化方針の違いを記載した記事になります。

## 本記事を記載するに至った直面した問題
以前ALB のアクセスログ出力先に S3(SSE-KMS 暗号化)を設定したところ、
アクセスログが出力されないエラーが発生しました。
本エラーに直面した際に各キーの違いを調査しようと考えました。

## 結論
SSE-KMS では以下一部の機能利用時にエラーが発生します。
そのため以下機能の利用が必須であれば`SSE-S3`の利用が必要となります。

### 主にエラーとなるケース
- S3アクセスログ出力先バケットに、`SSE-KMS`暗号化バケットを設定していた場合
- S3インベントリ出力先バケットに、`SSE-KMS`暗号化バケットを設定していた場合
- ALBアクセスログ出力先バケットに、`SSE-KMS`暗号化バケットを設定していた場合
- NLBアクセスログ出力先バケットに、`SSE-KMS`暗号化バケットを設定していた場合

## S3 サーバーサイド暗号化のおさらい

### S3 サーバーサイド暗号化の種類

S3 におけるサーバーサイド暗号化オプションは以下 5 パターンに分類できます。

1. SSE-S3
2. SSE-KMS(AWS マネージドキー)
3. SSE-KMS(カスタマーマネージドキー)
4. SSE-C
5. DSSE-KMS

### 暗号化の特徴
今回は利用が限定的な「SSE-C」「DSSE-KMS」は除外した上で、
「SSE-S3」「SSE-KMS(AWS マネージドキーカスタマー)」「SSE-KMS(カスタマーマネージドキー)」の特徴を確認します。

#### SSE-S3
S3 暗号化の中で最もシンプルな暗号化。
AWS側がキーの生成・管理・保管を行うためユーザはキーの管理が不要となります。

■主な特徴
- コスト
    - 利用料無料
- 監査
    - いつ/誰がキーを利用したのか追跡不可
- アクセス制御
    - S3 へのアクセス権限がある場合、透過的(リクエスト側設定不要)に利用できるため制御不可
- 拡張性
    - 設定追加/変更不可能
- 運用性
    - AWS マネージドにつき運用不要、不定期で自動ローテーション

#### SSE-KMS(AWS マネージドキー)
EBS や RDS の暗号化でおなじみ`aws/{サービス名}`(aws/rds、aws/ebs 等)の名前を持つ暗号化キーです。
SSE-S3 の利便性と KMS(カスタマーマネージドキー)の一部機能を備えています。
若干のカスタマイズ性と監査が可能な点が SSE-S3 との違いになります。

■主な特徴
- コスト
    - 作成・保管無料だがAPI リクエストごとに料金発生
- 監査
    - 利用時は API が発行されるため、CloudTrail より確認可能
- アクセス制御
    - AWS 側がサービス単位で利用を制限するキーポリシーを付与(ポリシー変更不可)
    - AWS 側で設定しているポリシーを満たしていれば透過的(リクエスト側設定不要)に利用できるため制御不可
    - ポリシー内容も RDS 用のキー(aws/rds)は同一アカウント内の全 RDS からリクエスト可能など、広く設定されている
- 拡張性：
    - 設定追加/変更不可能
- 運用性：
    - AWS マネージドにつき運用不要+１年単位で自動ローテーション
- その他注意点：
  - API コールにリクエストの制限があるので、短時間で大量のリクエストを実施する場合は注意(マネージドキーでも制限あり)
  - 後述する一部 S3 の機能を利用できない

#### SSE-KMS(カスタマーマネージドキー)

ユーザーが AWS KMS を利用してキーの生成・管理・保管を行うことができます。
任意のキーを使用/キー自体を管理できるユーザ制御/キーポリシーを設定して利用元を制限することも可能です。
柔軟な設定が可能な分コストも発生します。

- コスト
    - 有料(1$/キー+リクエストごとの課金+オプションごとに別途課金)
- 監査
    - 利用時は API が発行されるため、CloudTrail より確認可能
- アクセス制御
    - キー自体の管理者設定/キーポリシーを用いて利用元を制限することも可能
- 拡張性
    - 任意のキー/暗号化タイプの変更などの設定可能
- 運用性
    - AWS マネージドにつき運用不要+オプションにより自動ローテーション可能
- その他注意点：
  - API コールにリクエストの制限があるので、短時間で大量のリクエストを実施する場合は注意(マネージドキーでも制限あり)
  - 後述する一部 S3 の機能を利用できない
  - キーローテーションで作成されたキーを用いてデータの再暗号化が行われないため、旧/新キーを持ち続けることになる。そのためコストがバージョンごとに発生

メリット/デメリットも踏まえた一覧は以下の通りであり。
主な検討観点としては「コスト」「監査証跡」「キーに対するアクセス制御」かと思います。
| 項目 | SSE-S3 | SSE-KMS(AWS マネージド) | SSE-KMS(カスタマーマネージド) |
|----------|-----------------------------------|-------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------|
| ★ コスト | 〇(利用料無料) | △(リクエストごとに課金) | × (1$/キー+リクエストごとのに課金+オプションごとに別途課金) |
| ★ 監査証跡 | ×(追跡不可) | 〇(CloudTrail から確認可) | 〇(CloudTrail から確認可) |
| ★ アクセス制御 | ×(S3 へのアクセス権限がある場合、制御不可) | △(AWS 側キーポリシーを付与(ポリシー変更不可)、<br/> ポリシー内容も 同一アカウント内のサービスからリクエスト可能など、広く設定されている) | 〇(キー自体の管理者設定/キーポリシーを設定して利用元を制限することも可能) |
| 拡張性 | ×(設定追加/変更不可能) | ×(設定追加/変更不可能) | 〇(任意のキー/暗号化タイプの変更などの設定可能) |
| 運用性 | 〇(AWS マネージドにつき運用不要、不定期で自動ローテーション) | 〇(AWS マネージドにつき運用不要+１年単位で自動ローテーション) | 〇(AWS マネージドにつき運用不要+オプションにより自動ローテーション可能) |
| 特筆すべき注意点 | ・監査不可につき、監査要件がある場合は利用が厳しい | ・API コールにリクエストの制限がある <br/>・後述する一部 S3 の機能を利用できない | ・API コールにリクエストの制限がある <br/>・後述する一部 S3 の機能を利用できない<br/>・キーローテーションで作成されたキーを用いてデータの再暗号化が行われないため、旧/新キーを持ち続けることになる(コスト ↑) |

また、繰り返しとなりますが以下用途においてサポートされている、
バケット暗号化方式は「S3-SSE」一択となります。

- S3アクセスログの出力先バケットとして使用する予定がある
- S3インベントリの出力先バケットとして使用する予定がある
- ALBアクセスログ出力先バケットとして使用する予定がある
- NLBアクセスログ出力先バケットとして使用する予定がある

## SSE-KMSを使用した場合に使用できないS3の機能

### S3 アクセスログの出力先バケットに、`SSE-KMS`暗号化バケットを設定していた場合

#### 概要

S3 アクセスログは S3 に対するリクエストを記録するログとなります。
外部攻撃や不審なリクエストを受信した際のセキュリティ/アクセス監査に役立つ機能となります。

ログの内容としては、「リクエスト元 IP」「リクエスト対象オブジェクト」「日時」「リクエストメッセージ」など、監査に役立つ内容が集約されています。

#### 設定時の注意点
設定時にエラーが発生しないため、一見設定が行えているようにみえます。
ただし、内部的にエラーが発生しておりログは出力されません。

#### 改善方法

宛先バケットが SSE-S3 なら問題ないため暗号化方式を`SSE-S3`に変更する。
この機能を使用しつつ、KMS 利用のメリットを受けることはできないので設計時点で検討が必要になります。
なお、出力元(バケット A)と出力先(バケット B)の暗号化パターンによる設定可否は以下の通りです。
| 項番 | 出力(〇/×) | 暗号化内容 |
|----|-----------|--------------------------------------------------------------------------------|
| ① | 〇 | S3(バケット A)を「SSE-S3」暗号化設定。S3(バケット B)を「SSE-S3」暗号化設定。 |
| ② | × | S3(バケット A)を「SSE-S3」暗号化設定。S3(バケット B)を「SSE-KMS(aws/s3)」暗号化設定。 |
| ③ | × | S3(バケット A)を「SSE-S3」暗号化設定。S3(バケット B)を「SSE-KMS(カスタマーマネージドキー)」暗号化設定。 |
| ④ | 〇 | S3(バケット A)を「SSE-KMS(aws/s3)」暗号化設定。S3(バケット B)を「SSE-S3」暗号化設定。 |
| ⑤ | × | S3(バケット A)を「SSE-KMS(aws/s3)」暗号化設定。S3(バケット B)を「SSE-KMS(aws/s3)」暗号化設定。 |
| ⑥ | × | S3(バケット A)を「SSE-KMS(aws/s3)」暗号化設定。S3(バケット B)を「SSE-KMS(カスタマーマネージドキー)」暗号化設定。 |
| ⑦ | 〇 | S3(バケット A)を「SSE-KMS(カスタマーマネージドキー)」暗号化設定。S3(バケット B)を「SSE-S3」暗号化設定。 |
| ⑧ | × | S3(バケット A)を「SSE-KMS(カスタマーマネージドキー)」暗号化設定。S3(バケット B)を「SSE-KMS(aws/s3)」暗号化設定。 |
| ⑨ | × | S3(バケット A)を「SSE-KMS(カスタマーマネージドキー)」暗号化設定。S3(バケット B)を「SSE-KMS(カスタマーマネージドキー)」暗号化設定。 |

#### 参考先

[サーバーアクセスログ有効化](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/enable-server-access-logging.html)
[サーバーアクセスログ形式](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/LogFormat.html)

### S3 インベントリのターゲットバケットに、`SSE-KMS`暗号化バケットを設定していた場合

#### 概要

S3 インベントリは S3 に保管されたオブジェクトのリストを出力する機能となります。
出力形式/頻度/出力項目など限られた範囲ではありますが、設定の上レポートとして出力が可能です。

#### 改善方法

宛先バケットが SSE-S3 なら問題ないため暗号化方式を`SSE-S3`に変更する。
この機能を使用しつつ、KMS 利用のメリットを受けることはできないので設計時点で検討が必要になります。
なお、出力元(バケット A)と出力先(バケット B)の暗号化パターンは S3 アクセスログ出力パターンと同様です。

#### 設定時の注意点
設定時にエラーが発生しないため、一見設定が行えているようにみえます。
ただし、内部的にエラーが発生しておりログは出力されません。

### ALB アクセスログ出力先バケットに、`SSE-KMS` 暗号化バケットを設定していた場合

#### 概要

ALB アクセスログは ALB に対するリクエストを記録するログとなります。
5tuple(送信元 IP、送信元ポート番号、宛先 IP、宛先ポート番号、プロトコル番号)やターンアラウンドタイム/レスポンスステータスなど、
リクエスト調査に役立つ機能となります。

#### 改善方法

宛先バケットが SSE-S3 なら問題ないため暗号化方式を`SSE-S3`に変更する。
この機能を使用しつつ、KMS 利用のメリットを受けることはできないので設計時点で検討が必要になります。
なお、出力元(バケット A)と出力先(バケット B)の暗号化パターンは S3 アクセスログ出力パターンと同様です。

#### NLB アクセスログの出力先バケットに、`SSE-KMS(AWS マネージドキー)`暗号化バケットを設定していた場合

#### 概要

NLB アクセスログは NLB に対するリクエストを記録するログとなります。
ALB と出力情報で異なる部分があるが用途としては同様にリクエスト調査に役立つ機能となります。
また、注意点としてリスナープロトコルを`TLS`を設定する必要がある。

#### 改善方法

宛先バケットが SSE-S3 なら問題ないため暗号化方式を`SSE-S3`もしくは`SSE-KMS(カスタマーマネージドキー)`に変更する。
この機能を使用しつつ、KMS 利用のメリットを受けることはできないので設計時点で検討が必要になります。
なお、出力元(バケット A)と出力先(バケット B)の暗号化パターンによる設定可否は以下の通りです。
| 項番 | 出力(〇/×) | 暗号化内容 |
|----|-----------|--------------------------------------------------------------------------------|
| ① | 〇 | S3(バケット A)を「SSE-S3」暗号化設定。S3(バケット B)を「SSE-S3」暗号化設定。 |
| ② | × | S3(バケット A)を「SSE-S3」暗号化設定。S3(バケット B)を「SSE-KMS(aws/s3)」暗号化設定。 |
| ③ | 〇 | S3(バケット A)を「SSE-S3」暗号化設定。S3(バケット B)を「SSE-KMS(カスタマーマネージドキー)」暗号化設定。 |
| ④ | 〇 | S3(バケット A)を「SSE-KMS(aws/s3)」暗号化設定。S3(バケット B)を「SSE-S3」暗号化設定。 |
| ⑤ | × | S3(バケット A)を「SSE-KMS(aws/s3)」暗号化設定。S3(バケット B)を「SSE-KMS(aws/s3)」暗号化設定。 |
| ⑥ | 〇 | S3(バケット A)を「SSE-KMS(aws/s3)」暗号化設定。S3(バケット B)を「SSE-KMS(カスタマーマネージドキー)」暗号化設定。 |
| ⑦ | 〇 | S3(バケット A)を「SSE-KMS(カスタマーマネージドキー)」暗号化設定。S3(バケット B)を「SSE-S3」暗号化設定。 |
| ⑧ | × | S3(バケット A)を「SSE-KMS(カスタマーマネージドキー)」暗号化設定。S3(バケット B)を「SSE-KMS(aws/s3)」暗号化設定。 |
| ⑨ | 〇 | S3(バケット A)を「SSE-KMS(カスタマーマネージドキー)」暗号化設定。S3(バケット B)を「SSE-KMS(カスタマーマネージドキー)」暗号化設定。 |


### CloudFormatin 利用時の注意

CloudFormation で S3 と ALB を構築する場合、
S3(SSE-KMS 暗号化)に対し ALB のアクセスログ出力設定時にエラーが表面化せずに CFn デプロイが成功となる。
そのため、構築時に気づかず設定(ログは出力されない)されてしまうことに注意が必要です。

![2024-01-30_22h04_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1764568/dcba7a25-47ce-1dba-94d5-eff7a80eb030.png)

ただし、CloudTrailで`ModifyLoadBalancerAttributes`イベント確認するとerrorMessageを確認できる。
※SSE-S3を設定したバケットからSSE-KMSに変更した場合本エラーが発生。
　バケットポリシー自体は正しく設定できていることは確認済み。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1764568/d5126829-adf6-9183-bffa-3490f9e4f81b.png)


## 参考
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/UsingServerSideEncryption.html

https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html

https://docs.aws.amazon.com/ja_jp/kms/latest/developerguide/requests-per-second.html

https://docs.aws.amazon.com/ja_jp/kms/latest/developerguide/concepts.html#key-mgmt