【初心者】AWS Key Management Service (AWS KMS) を使ってみる #2 (S3暗号化での利用)

# 1. 目的
- AWSのセキュリティ関連サービスの復習をしている。AWS KMSについて、前回の記事「[【初心者】AWS Key Management Service (AWS KMS) を使ってみる](https://qiita.com/mksamba/items/a7e902c6d5a12f2a36dc)」でEC2インスタンス内のファイルの暗号化、復号を試してみたが、今回はS3での動作確認を行う。
- 今ひとつKMSのメリットが理解できていないため、S3の標準機能で暗号化したバケットとの動作比較を行う。

# 2. やったこと

- 2つの空のバケットを作成する。※作業に使用したバケットは記事公開時に削除済。
    - mksamba-bucket-sse-s3 (S3の標準機能での暗号化)
    - mksamba-bucket-sse-kms (KMSでの暗号化)

- Lambda関数からそれぞれのバケットにファイルを書き込む。
   
- 2人のIAMユーザを作成する。
    - mksamba-poweruser (S3権限あり、KMS権限あり)
    - mksamba-normaluser (S3権限あり、KMS権限なし)

- IAMユーザの権限の違いによるバケット内のデータの見え方の違いを確認する。

- バケットを誤って一般公開してしまったとして、インターネット経由でのそれぞれのバケット内のデータの見え方の違いを確認する。

# 3. 構成図

![kms-s3-構成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/a2e7fcc8-1435-e7d1-e33c-a85eea1f2971.png)




# 4. 実施手順

## 4.1 2つのバケットの作成
- 以下の2つのバケットを作成する。
    - mksamba-bucket-sse-s3 (S3の標準機能での暗号化)
    - mksamba-bucket-sse-kms (KMSでの暗号化)
    
- S3標準機能で暗号化する場合の設定は以下のとおり。

![kmss3-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/1365a2bf-258b-2ad8-3815-06a323269854.png)


- KMSで暗号化する場合の設定は以下のとおり。

![kmss3-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/b1b16b8c-ac68-93ec-b222-e71e95bc1fc1.png)



- なお、KMSでの暗号化設定時に使用する鍵(KMSマスターキー)は、事前に作成しておいた「カスタマー管理型のキー(CMK)」を用いる。また、その鍵に対するキーポリシーはデフォルト設定とする。（同一アカウント内の、KMSに関する権限を持つIAMユーザ/ロールからはアクセス可能)


## 4.2 バケットへのファイルの書き込み
- 2つのバケットにファイルを書き込むLambda関数を作成する。

``` mksamba-s3-write.py
import datetime
import boto3

s3 = boto3.resource('s3') 

def lambda_handler(event, context):
    dt_now = datetime.datetime.now()
    key = str(dt_now) + ".txt"   #結果を保存するファイル名を"日時.txt"とする

    tmpfile = open('/tmp/tmp.txt', 'w', encoding='utf-8')
    print(str(dt_now), file=tmpfile)
    tmpfile.close()
    
    bucket = "mksamba-bucket-sse-s3"
    s3.meta.client.upload_file('/tmp/tmp.txt',bucket,key)
    
    bucket = "mksamba-bucket-sse-kms"
    s3.meta.client.upload_file('/tmp/tmp.txt',bucket,key)  
```

- この関数に付与するロールの権限として、最初はAmazonS3FullAccessのみを付与する。そうすると、mksamba-bucket-sse-s3には書き込みできるが、mksamba-bucket-sse-kmsのほうには以下の書き込みエラーとなる。

```
[ERROR] S3UploadFailedError: Failed to upload /tmp/tmp.txt to mksamba-bucket-sse-kms/2021-02-28 15:05:16.538885.txt: 
An error occurred (AccessDenied) when calling the PutObject operation: 
Access DeniedTraceback (most recent call last):  
File "/var/task/lambda_function.py", line 20, in lambda_handler    
s3.meta.client.upload_file('/tmp/tmp.txt',bucket,key)  
```

- ロールにKMSの権限を追加する。(AWS管理ポリシーの「AWSKeyManagementServicePowerUser」では権限不足のようで、今回は「PowerUserAccess」を追加) その後、再度Lambda関数を実行すると、ファイルが両方のバケットに保存されるようになる。
- この挙動から、KMSで暗号化されたS3バケットへの書き込み時に、KMS(の中の鍵)へのアクセス権限が必要なことが分かる。

## 4.3 2人のIAMユーザの権限の違いによる動作確認
- 権限の異なる2人のIAMユーザを作成する。
    - mksamba-poweruser (AdministratorAccess: S3及びKMS権限あり)
    - mksamba-normaluser (S3FullAccessのみ: S3権限あり、KMS権限なし)
- IAMユーザ「mksamba-poweruser」でログインした場合、両方のバケットのファイル一覧の表示、およびダウンロードが可能。
- IAMユーザ「mksamba-normaluser」でログインした場合、バケット「mksamba-bucket-sse-s3」のほうは問題なくファイル一覧の表示やファイルのダウンロードが可能。一方、バケット「mksamba-bucket-sse-kms」のほうは、ファイルの一覧の表示は可能だが、ファイルをダウンロードしようとするとエラーになる。
- mksamba-normaluser でログインした場合、バケットのリスト表示は以下のように可能。

![kmss3-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/7bfe32e2-d5d6-07b8-e7ad-2240ac3fc9a1.png)

- 次に、ファイルを選択し、ダウンロードしようとすると以下のエラー(Access Denied)となる。

![kmss3-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/6246fee4-3266-25de-df37-de2ff4b5a17b.png)

- この挙動から、KMS暗号化されているバケットの場合、S3のアクセス権限があればファイルのリストの表示は可能だが、ファイルのダウンロードにはKMSのアクセス権(バケットの暗号化に使用している暗号鍵を使ったDecryptの権限)が必要なことが分かる。

## 4.4 バケットを公開する設定にした場合の動作確認

- 2つのバケットに対し、バケットを一般公開する設定を行う。設定内容は公式ドキュメント[「静的ウェブサイトホスティング用に S3 バケットを設定する方法」](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/user-guide/static-website-hosting.html)をそのまま実施する。
    - 静的ウェブサイトホスティングの有効化
    - S3 パブリックアクセスブロック設定の変更（全てのチェックを外す）
    - バケットポリシー（Readの許可）の追加

- バケット「mksamba-bucket-sse-s3」では、上記の設定後、オブジェクト（ファイル）のURLを指定すると、誰でもダウンロード、閲覧することが可能。
- バケット「mksamba-bucket-sse-kms」では、上記の設定後、オブジェクト（ファイル）のURLを指定してダウンロードしようとすると、以下のエラーとなりダウンロード不可となる。

![kmss3-05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/ba018b1e-27dd-33ff-0d74-4de191a9a8bb.png)

- 上記の挙動から、SSE-S3で暗号化している場合、ファイルの取得要求をするとAWS側で自動復号されてしまうため、論理的なレベルでのアクセスに対するセキュリティの向上にはなっていないと考えられる。（AWSのデータセンターからディスクが盗まれても、暗号化されているので大丈夫、という物理的なレベルのでのセキュリティ対策にはなっている。）
- 一方SSE-KMSの場合、KMS(の中の鍵)のアクセス権限がないとファイルの復号、ダウンロードができないため、AWSアカウント内でのKMS権限を持たないユーザや、誤設定によるバケットの公開による一般ユーザからのアクセスに対してのセキュリティ対策となっている。

# 5. 所感
- どのようなリスクから守りたいかということを意識して暗号化の設定を選択するようにしたい。