【初心者】AWS Key Management Service (AWS KMS) を使ってみる

# 1. 目的
- AWSのセキュリティ関連サービスの復習をしている。AWS KMSについて、暗号鍵の登録や、ファイルの暗号化・復号といった基本的な処理を行い、動作イメージを把握する。

# 2. AWS KMSとは(自分の理解)
- データを暗号化するための鍵の管理を行ってくれるサービス。暗号鍵をAWSの責任範囲において保管したり、更新したりしてくれる。

# 3. やったこと
- CMK(カスタマーマスターキー) を作成する。
- CMKに紐づくデータキーを作成する。
- データキーで自分のファイルを暗号化する。
- （暗号化されたデータキー及び暗号化されたファイルを残し、元のファイルを削除する。）
- 暗号化されたデータキーを復号し、復号したデータキーを用いて暗号化されたファイルも復号する。

![kmsの図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/1ec649e8-95cf-d191-a22b-1137ac9bc90e.png)




# 4. 予習
先人のまとめを読んで勉強する。

- [「10分でわかる！Key Management Serviceの仕組み」](https://dev.classmethod.jp/articles/10minutes-kms/)
    - 2014年の古い記事だが、マスターキーやデータキーなどの概念の説明が非常に分かりやすい。
- [「AWS KMSを使って秘密鍵を管理する」](http://yebisupress.dac.co.jp/2017/03/30/aws-kms%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E7%A7%98%E5%AF%86%E9%8D%B5%E3%82%92%E7%AE%A1%E7%90%86%E3%81%99%E3%82%8B/)
    - こちらも2017年の記事で新しくはないが、暗号化・復号の手順が分かりやすく、この記事に記載されている手順をなぞっていくことで動作を確認する。
    
# 5. 実施手順
## 5.1 CMK(カスタマーマスターキー)の作成
- まずはマネージメントコンソールにて、KMSでの暗号化処理を行う際のベースとなる、CMK(カスタマーマスターキー)を作成する。
- KMSのメニューから「カスタマー管理型のキー」を開き、「キーの作成」を選択する。

![kms01a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/4c6ecbec-57ae-e6cd-c2e3-6ae5ad53199e.png)

- キーのタイプを「対称」、キーマテリアルオリジンを「KMS」とする。※タイプを「対称」とすることでCMKがAES 265bitのものになる。また、オリジンを「KMS」とすることで、KMSのサービス用の領域の中に、AWSが生成し管理するCMKが作成される。

![kms02a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/5082874b-7398-3cb0-b039-28140969c8f4.png)

- エイリアス(名前) を 「mksamba-masterkey」とする。

![kms03a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/91d10128-5c3e-5ac4-9b21-6e189f3ba0a6.png)

- キー管理者を追加する。今回はIAMユーザ（自分）を指定。キー管理者はキーの有効・無効化、更新、削除が可能。

![kms04a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/673469c4-1c87-5a9d-2e5e-fa73fa436489.png)

- キーの使用許可者を追加する。今回はIAMユーザ（自分）を指定。キーの使用許可者は、キーを用いた暗号化、復号の処理を行うことが可能。

![kms05a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/e0a2dad7-87ae-a56c-6d42-7e3eb39cd94e.png)

- キーポリシーの内容を確認する。前の手順で追加したキー管理者、キー使用許可者とは別に、初期設定値として、自AWSアカウントのIAMユーザでKMSへのアクセス権があるユーザに対しては全ての操作が許可されている。

![kms06a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/07311072-18a1-e585-6034-8da42e49db10.png)

- 作成したCMK(mksamba-masterkey)が表示されていることを確認する。メニューから有効化、無効化、削除のスケジューリングが可能。作成したCMKの中身は見ることができない。

![kms08a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/4d1f753d-198a-a811-f1ea-da348d5e18c6.png)

## 5.2 データキーの作成

- CMKに紐づくデータキーを作成する。CMK自体を用いてデータを直接暗号化することもできるが、通常は実際に実データの暗号化処理を行うためのデータキーを発行して、それを用いて暗号化を行う。
- ここからはCLIを用いて操作を行う。

```
# AWS CLIバージョンの確認
[ec2-user@ip-10-0-0-126 ~]$ aws --version
aws-cli/2.1.24 Python/3.7.3 Linux/4.14.214-160.339.amzn2.x86_64 exe/x86_64.amzn.2 prompt/off

# KMSのAPI(GenerateDatakey)を用いて、CMKに紐づくデータキーを作成
[ec2-user@ip-10-0-0-126 ~]$ aws kms generate-data-key --key-id arn:[mksamba-masterkeyのARN] --key-spec AES_256
{
    "CiphertextBlob": "[encrypted-datakey-string]",
    "Plaintext": "[plain-datakey-string]",
    "KeyId": "arn:aws:kms:ap-northeast-1:xxxxxxxxxxxx:key/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
```
- "Plaintext"がデータキーそのもの、"CiphertextBlob"がCMKにより暗号化されて、かつbase64エンコードされたデータキーとなる。
- "Plaintext"は、文字列をそのままコピペして、ファイル"plain-datakey"として保存する。
- "CiphertextBlob"は、文字列をコピペして、base64デコードして、ファイル"encrypted-datakey"として保存する。

```
[ec2-user@ip-10-0-0-126 ~]$ echo [plain-datakey-string] > plain-datakey
[ec2-user@ip-10-0-0-126 ~]$ echo [encrypted-datakey-string] | base64 --decode > encrypted-datakey
```

# 5.3 ファイルの暗号化

- 作成したデータキーを用いてファイルの暗号化を行う。

```
# 暗号化したいファイルの確認
[ec2-user@ip-10-0-0-126 ~]$ cat plain-document
休みがほしい。温泉に行きたい。

# データキーを用いて暗号化する。
# 元ファイル"plain-document"を、暗号鍵"plain-datakey"を用いてaes-256-cbcモードで暗号化して、ファイル"encrypted-document"として保存する。
[ec2-user@ip-10-0-0-126 ~]$ openssl aes-256-cbc -e -in plain-document -out encrypted-document -pass file:plain-datakey

# 暗号化されていることの確認
[ec2-user@ip-10-0-0-126 ~]$ cat encrypted-document
縒唳9楳H??合й偉(碁Ra@?肄?;X・^

```
- 暗号化処理が終わった後、本来は安全のため、元ファイル"plain-document"、及び暗号化されていないデータキー"plain-datakey"を削除する必要がある。今回は復号後の動作確認のためそのままにしておくが、復号時はこれらのファイルが存在しない前提で復号処理を行う。
- データキーを用いて暗号化する仕組みが「Envelope Encryption」と呼ばれている。今回のケースだと、暗号化されたデータキー"encrypted-datakey" が封筒(Envelope)で、暗号化されたファイル"encrypted-document"が便箋で、便箋に書かれた内容が封筒に入っていて外からは読めないイメージととらえた。

# 5.4 ファイルの復号

- 先の手順で暗号化したファイルを復号する。

```
# KMSのAPI(Decrypt)を用いて、まず暗号化されたデータキーを復号する。
[ec2-user@ip-10-0-0-126 ~]$ aws kms decrypt --ciphertext-blob fileb://encrypted-datakey --output text --query Plaintext > decrypted-datakey

# データキーを作成した時に入手した、暗号化前のデータキーと比較し、データが一致することを確認する。
[ec2-user@ip-10-0-0-126 ~]$ diff plain-datakey decrypted-datakey
[ec2-user@ip-10-0-0-126 ~]$

# 復号後のデータキーを用いて、暗号化したファイルを復号する。元通りになっていることを確認する。
[ec2-user@ip-10-0-0-126 ~]$ openssl aes-256-cbc -d -in encrypted-document -pass file:decrypted-datakey
休みがほしい。温泉に行きたい。
```
- この後、復号後のデータキーを削除して復号処理全体が完了となる。
- decryptの際に、CMKのKeyIDを指定しなくても大丈夫なのか疑問に思ったが、aws kms cli の help 内の記載によると、CMKがsymmetricの場合にはCMKのKeyIDを指定することは必須ではなく、metadataを用いて適切なCMKが自動的に選択されるとのこと。


# 6. 所感
- 一応、原理としてはどのような仕組みになっているのかを確認することができた。S3やRDSなどのデータを暗号化する際にどのように応用されているのかなどはまた確認してみたい。