[JAWS-UG CLI] Amazon KMS 入門 (2) データの暗号化・復号化

# このハンズオンについて

この手順は、[JAWS-UG CLI専門支部 #58 KMS入門](https://manage.doorkeeper.jp/groups/jawsug-cli/events/41911)で実施したものです。


# 前提条件

## 必要な権限

作業にあたっては、以下の権限を有したIAMユーザもしくはIAMロールを利用してください。

- KMSに対するフルコントロール権限
- S3に関するフルコントロール権限
- STSに関するフルコントロール権限
- IAMに関するフルコントロール権限


# 0. 準備

## 0.1. リージョンを指定

```bash:コマンド
export AWS_DEFAULT_REGION='ap-northeast-1'
```

## 0.2. 資格情報を確認


```bash:コマンド
aws configure list
```

インスタンスプロファイルを設定したEC2インスタンスでアクセスキーを設定せずに実行した場合、以下のようになります。

```text:結果
Name                    Value             Type    Location
----                    -----             ----    --------
profile                <not set>             None    None
access_key     ****************RDPA         iam-role
secret_key     ****************9GA8         iam-role
region           ap-northeast-1              env    AWS_DEFAULT_REGION
```

## 0.3. バージョン確認

```bash:コマンド
aws --version
```

```text:結果
aws-cli/1.10.56 Python/2.7.10 Linux/4.4.15-25.57.amzn1.x86_64 botocore/1.4.46
```

## 0.4. バージョンアップ（必要に応じて）

```bash:コマンド
sudo pip install -U awscli
```

## 0.5. 変数の設定

この手順の前に定義しておくべき変数を設定します。

```bash:コマンド
USER_NAME='jawsug-cli-user'

ALIAS="alias/cli-handson0815"

KEY_ID=$(aws kms list-aliases \
    --query "Aliases[?AliasName == \`${ALIAS}\`].TargetKeyId" \
    --output text) \
    && echo ${KEY_ID}
```

# 1. 利用者情報の認証情報取得

一般ユーザの認証情報を生成し、プロファイルとして設定します。

## 1.1. access keyの作成と取得

### 変数の確認

```bash:コマンド
cat << ETX

    USER_NAME: ${USER_NAME}

ETX
```

```text:結果

    USER_NAME: jawsug-cli-user

```

### access keyの作成と取得

```bash:コマンド
aws iam create-access-key \
    --user-name ${USER_NAME} \
    > ${USER_NAME}.json \
    && cat ${USER_NAME}.json
```

```json:結果:
{
    "AccessKey": {
        "UserName": "jawsug-cli-user",
        "Status": "Active",
        "CreateDate": "2016-08-06T05:55:49.222Z",
        "SecretAccessKey": "****************************************",
        "AccessKeyId": "********************"
    }
}
```

### アクセスキーの抽出

```bash:コマンド
USER_ACCESS_KEY=$( \
    cat ${USER_NAME}.json \
    | jp.py 'AccessKey.AccessKeyId' \
    | sed 's/"//g') \
    && echo ${USER_ACCESS_KEY}

USER_SECRET_ACCESS_KEY=$( \
    cat ${USER_NAME}.json \
    | jp.py 'AccessKey.SecretAccessKey' \
    | sed 's/"//g') \
    && echo ${USER_SECRET_ACCESS_KEY}
```

## 1.2. プロファイル名の指定

```bash:コマンド
USERS_PROFILE_NAME=${USER_NAME}
```

## 1.3. プロファイルの確認

プロファイル名が未使用であることを確認します。

```bash:コマンド
aws configure get aws_access_key_id \
    --profile ${USERS_PROFILE_NAME}
```

```text:結果
The config profile (jawsug-cli-user) could not be found
```


```bash:コマンド
aws configure get aws_secret_access_key \
    --profile ${USERS_PROFILE_NAME}
```

```text:結果
The config profile (jawsug-cli-user) could not be found
```


```bash:コマンド
aws configure get region \
    --profile ${USERS_PROFILE_NAME}
```

```text:結果
The config profile (jawsug-cli-user) could not be found
```


## 1.4. プロファイルの作成

### 変数の確認

```bash:コマンド
cat << ETX

    USER_NAME: ${USER_NAME}
    ACCESS_KEY: ${USER_ACCESS_KEY}
    SECRET_ACCESS_KEY: ${USER_SECRET_ACCESS_KEY}
    REGION: ${AWS_DEFAULT_REGION}

ETX
```

```text:結果

    USER_NAME: jawsug-cli-user
    ACCESS_KEY: ********************
    SECRET_ACCESS_KEY: ***********************************
    REGION: ap-northeast-1

```


### プロファイルの作成

```bash:コマンド
aws configure set aws_access_key_id ${USER_ACCESS_KEY} \
    --profile ${USERS_PROFILE_NAME}
```

```text:結果
（戻り値無し）
```

```bash:コマンド
aws configure set aws_secret_access_key ${USER_SECRET_ACCESS_KEY} \
    --profile ${USERS_PROFILE_NAME}
```

```text:結果
（戻り値無し）
```

```bash:コマンド
aws configure set region ${AWS_DEFAULT_REGION} \
    --profile ${USERS_PROFILE_NAME}
```

```text:結果
（戻り値無し）
```

## 1.5. 認証情報の確認（.aws/credentials）

```bash:コマンド
cat ~/.aws/credentials
```

```text:結果（例）
[jawsug-cli-user]
aws_access_key_id = ********************
aws_secret_access_key = ***********************************
```

## 1.6. 認証情報の確認（.aws/config）

```bash:コマンド
cat ~/.aws/config
```

```text:結果（例）
[profile jawsug-cli-user]
region = ap-northeast-1
```



# 2. ユーザの切り替え

一般ユーザのプロファイルに切り替えます。

## 2.1. 現在のユーザの確認

あとで現在の状態に戻るため、一応結果を控えておいてください。（以下の結果は、インスタンスプロファイルを利用している場合）

```bash:コマンド
aws configure list
```

```text:結果（例）
      Name                    Value             Type    Location
      ----                    -----             ----    --------
   profile                <not set>             None    None
access_key     ****************CIIA         iam-role
secret_key     ****************wGIk         iam-role
    region           ap-northeast-1              env    AWS_DEFAULT_REGION
```


## 2.2. 切替後ユーザの確認

```bash:コマンド
cat << ETX

    USERS_PROFILE_NAME: ${USERS_PROFILE_NAME}

ETX
```

```text:結果

    USERS_PROFILE_NAME: jawsug-cli-user

```


## 2.3. ユーザの切り替え

```bash:コマンド
export AWS_DEFAULT_PROFILE=${USERS_PROFILE_NAME}
```

## 2.4. 認証情報の確認

```bash:コマンド
aws configure list
```

```text:結果
      Name                    Value             Type    Location
      ----                    -----             ----    --------
   profile          jawsug-cli-user           manual    --profile
access_key     ****************QNVA shared-credentials-file
secret_key     ****************fTJ+ shared-credentials-file
    region           ap-northeast-1              env    AWS_DEFAULT_REGION
```


# 3. データの暗号化

## 3.1. データキーの生成

```bash:コマンド
aws kms generate-data-key \
    --key-id ${KEY_ID} \
    --key-spec AES_256 \
    > ${KEY_ID}.json \
    && cat ${KEY_ID}.json
```

```json:結果
{
    "Plaintext": "********************************************",
    "KeyId": "arn:aws:kms:ap-northeast-1:************:key/********-****-****-****-************",
    "CiphertextBlob": "AQEDAHiCRznQUHSBmR0PbOH+dC1yCIXtowgxaDBtcteu1VzqOAAAAH4wfAYJKoZIhvcNAQcGoG8wbQIBADBoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDMlTZXU8X/5Zct1vaAIBEIA7dZiDXkUn8BeUkDNidSwHfg9uxGEu9LJsyL1lMlJt3+J5zZAjw9FCy8qPt//8BOHkyD4Ivxm2rn2DEg0="
}
```

## 3.2. データキー（平文）の取り出し

暗号化が完了したら削除する予定です。

```bash:コマンド
PLAIN_DATA_KEY_FILE_NAME='plaintext.txt'
```

```bash:コマンド
cat ${KEY_ID}.json | jp.py 'Plaintext' | sed 's/"//g' \
    > ${PLAIN_DATA_KEY_FILE_NAME} \
    && cat ${PLAIN_DATA_KEY_FILE_NAME}
```


## 3.3. データキー（暗号化済）の取り出し

暗号化が完了しても、復号化の際に必要になるため削除せずに保管します。

```bash:コマンド
CIPHER_DATA_KEY_FILE_NAME='ciphertext_blob.txt'
```

データキーの復号化を想定し、BASE64でエンコードしておきます。

```bash:コマンド
cat ${KEY_ID}.json | jp.py 'CiphertextBlob' | sed 's/"//g' \
    | base64 --decode > ${CIPHER_DATA_KEY_FILE_NAME} \
    && cat ${CIPHER_DATA_KEY_FILE_NAME}
```

## 3.4. データファイルの生成

暗号化対象のテキストファイルを生成します。

```bash:コマンド
PLAIN_TEXT_FILE_NAME='non_encrypted.txt'

cat << EOF > ${PLAIN_TEXT_FILE_NAME}
hello, world!
EOF

cat ${PLAIN_TEXT_FILE_NAME}
```

## 3.5. 出力先ファイル名の指定

```bash:コマンド
ENCRYPTED_TEXT_FILE_NAME='encrypted.txt'
```

## 3.6. データの暗号化

### 変数の確認

```bash:コマンド
cat << ETX

    INPUT_FILE_NAME: ${PLAIN_TEXT_FILE_NAME}
    INPUT_FILE: $(cat ${PLAIN_TEXT_FILE_NAME})
    OUTPUT_FILE_NAME: ${ENCRYPTED_TEXT_FILE_NAME}
    PLAIN_DATA_KEY_FILE_NAME: ${PLAIN_DATA_KEY_FILE_NAME}
    PLAIN_DATA_KEY: $(cat ${PLAIN_DATA_KEY_FILE_NAME})

ETX
```

```text:結果

    INPUT_FILE_NAME: non_encrypted.txt
    INPUT_FILE: hello, world!
    OUTPUT_FILE_NAME: encrypted.txt
    PLAIN_DATA_KEY_FILE_NAME: plaintext.txt
    PLAIN_DATA_KEY: ********************************************

```

### データの暗号化

```bash:コマンド
openssl enc \
    -e \
    -aes-256-ecb \
    -in ${PLAIN_TEXT_FILE_NAME} \
    -out ${ENCRYPTED_TEXT_FILE_NAME} \
    -pass file:${PLAIN_DATA_KEY_FILE_NAME}
```

```text:結果
（戻り値無し）
```

## 3.7. データキー（平文）の破棄

平文のデータキーはきちんと削除しましょう。

```bash:コマンド
rm ${PLAIN_DATA_KEY_FILE_NAME}
```

# 4. データの復号化

## 4.1. データキー（暗号化済）の復号化

```bash:コマンド
DECRYPTED_DATA_KEY_FILE_NAME='decrypted_plaintext.txt'
```

```bash:コマンド
aws kms decrypt \
    --ciphertext-blob fileb://${CIPHER_DATA_KEY_FILE_NAME} \
    --query Plaintext \
    --output text \
    > ${DECRYPTED_DATA_KEY_FILE_NAME} \
    && cat ${DECRYPTED_DATA_KEY_FILE_NAME}
```

```text:結果
********************************************
```

結果がgenerate-data-keyで出力したPlaintextと一致していることを確認します。

```bash:コマンド
cat ${KEY_ID}.json | jp.py 'Plaintext' | sed 's/"//g' \
    > ${PLAIN_DATA_KEY_FILE_NAME} \
    && cat ${PLAIN_DATA_KEY_FILE_NAME}
```

```bash:コマンド
diff ${DECRYPTED_DATA_KEY_FILE_NAME} ${PLAIN_DATA_KEY_FILE_NAME}
```

```text:結果
（戻り値無し）
```

## 4.2. データの復号化

復号化したデータキーで暗号化した文章を復号化します。

```bash:コマンド
openssl enc \
    -d \
    -aes-256-ecb \
    -in ${ENCRYPTED_TEXT_FILE_NAME} \
    -out ${PLAIN_DATA_KEY_FILE_NAME} \
    -pass file:${DECRYPTED_DATA_KEY_FILE_NAME} \
    && cat ${PLAIN_DATA_KEY_FILE_NAME}
```

```text:結果
hello, world!
```

## 4.3. データキー（平文）の破棄

平文のデータキーはきちんと削除しましょう。
（大事なことなので2度言いました。）

```bash:コマンド
rm ${DECRYPTED_DATA_KEY_FILE_NAME}
rm ${PLAIN_DATA_KEY_FILE_NAME}
```


以上