[JAWS-UG CLI] Amazon KMS 入門 (3) S3へのファイルアップロード（SSE-KMSの場合）

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

この手順は、[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'
USERS_PROFILE_NAME=${USER_NAME}

AWS_ID=$(aws sts get-caller-identity \
    --query Account \
    --output text) \
    && echo ${AWS_ID}

ALIAS="alias/cli-handson0815"

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


# 1. ポリシーのアタッチ

一般ユーザに対してS3に対する権限を付与し、S3のデータを暗号化します。（Server-Side Encryption）

## 1.0 ユーザの切り替え

ここで、最初に利用していた認証情報に切り替えます。

インスタンスプロファイルを利用していた場合は、環境変数をリセットしてください。

```bash:コマンド
unset AWS_DEFAULT_PROFILE
```

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

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


別のプロファイルを利用していた場合には、プロファイルを切り替えてください。

```bash:コマンド
export AWS_DEFAULT_PROFILE='（切り替え前のプロファイル名）'
```

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

## 1.1. ARNの確認

```bash:コマンド
aws iam list-policies \
    --scope "AWS"
```

```text:結果
（省略）
```

## 1.2. ARNの指定

```bash:コマンド
ARN_S3='arn:aws:iam::aws:policy/AmazonS3FullAccess'
```

## 1.3. Managed Policyのアタッチ

### 変数の確認

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

    ARN_for_S3: ${ARN_S3}
    USER_NAME: ${USER_NAME}

ETX
```

### Managed Policyのアタッチ

```bash:コマンド
aws iam attach-user-policy \
    --user-name ${USER_NAME} \
    --policy-arn ${ARN_S3}
```

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

## 1.4. アタッチされたポリシーの確認

```bash:コマンド
aws iam list-attached-user-policies \
    --user-name ${USER_NAME}
```

```json:結果
{
    "AttachedPolicies": [
        {
            "PolicyName": "AmazonS3FullAccess",
            "PolicyArn": "arn:aws:iam::aws:policy/AmazonS3FullAccess"
        }
    ]
}
```

# 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:コマンド
BUCKET_NAME="kms-test-${AWS_ID}" \
    && echo ${BUCKET_NAME}
```

## 3.2. バケットの不存在を確認

```bash:コマンド
aws s3 ls s3://${BUCKET_NAME}
```

```text:結果
An error occurred (NoSuchBucket) when calling the ListObjects operation: The specified bucket does not exist
```

## 3.3. 変数の確認

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

    BUCKET_NAME: ${BUCKET_NAME}

ETX
```

```text:結果

    BUCKET_NAME: kms-test-************

```

## 3.4. バケットの作成

```bash:コマンド
aws s3 mb s3://${BUCKET_NAME}
```

```text:結果
make_bucket: s3://kms-test-************/
```


## 3.5. バケットの存在を確認

```bash:コマンド
aws s3 ls | grep ${BUCKET_NAME}
```

```text:結果
2016-08-07 05:33:25 kms-test-************
```



# 4. データのアップロード

## 4.1. ファイルの生成

```bash:コマンド
DATA_FILE='test.txt'

cat << EOF > ${DATA_FILE}
hogehoge
EOF

cat ${DATA_FILE}
```

```text:結果
hogehoge
```

## 4.2. 署名の確認

**All AWS KMS operations require Signature Version 4 .**とのこと。

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

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

## 4.3. 署名の設定

```bash:コマンド
aws configure set s3.signature_version s3v4 \
    --profile ${USERS_PROFILE_NAME}
```

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

## 4.4. 署名の確認

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

```text:結果
s3v4
```

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

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

## 4.5. ファイルのアップロード（パラメータの確認）

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

    DATA_FILE: ${DATA_FILE}
    BUCKET_NAME: ${BUCKET_NAME}
    KEY_ID: ${KEY_ID}

ETX
```

```text:結果

    DATA_FILE: test.txt
    BUCKET_NAME: kms-test-************
    KEY_ID: ********-****-****-****-************

```

## 4.6. ファイルのアップロード

```bash:コマンド
aws s3 cp ${DATA_FILE} s3://${BUCKET_NAME}/${DATA_FILE} \
    --sse-kms-key-id ${KEY_ID} \
    --sse aws:kms
```

```text:結果
upload: ./test.txt to s3://kms-test-************/test.txt
```


## 4.7. アップロードされたファイルの確認

```bash:コマンド
aws s3api head-object \
    --bucket ${BUCKET_NAME} \
    --key ${DATA_FILE}
```

```json:結果
{
    "AcceptRanges": "bytes",
    "ContentType": "text/plain",
    "LastModified": "Mon, 01 Aug 2016 10:18:49 GMT",
    "ContentLength": 9,
    "ETag": "\"********************************\"",
    "ServerSideEncryption": "aws:kms",
    "SSEKMSKeyId": "arn:aws:kms:ap-northeast-1:************:key/********-****-****-****-************",
    "Metadata": {}
}
```

# 5. ファイルのダウンロード

## 5.1. ダウンロードしたデータのファイル名を指定

```bash:コマンド
DOWNLOADED_DATA_FILE='test_downloaded.txt'
```

## 5.2. ファイルのダウンロード

```bash:コマンド
aws s3 cp s3://${BUCKET_NAME}/${DATA_FILE} ${DOWNLOADED_DATA_FILE}
```

## 5.3. データの確認

```bash:コマンド
cat ${DOWNLOADED_DATA_FILE}
```

```text:結果
hogehoge
```

アップロード時に暗号化する以外は、透過的に操作できました。

以上