GCP スキルバッジをもらおう　〜８. Getting Started with Cloud KMS

実際にラボを実施した際の記録を載せていきます。
学習の助けになったリンクや、後に見るための学習メモ、ちょっと迷った手順を書いていきます。
あと、コマンドも忘れたくないのでログしていきます。

* 学習の助けになったリンクは、「学習に役立つリンク」にまとめて書いてあります。
* 学習メモは:writing_hand:アイコンをつけてます。
* 迷った手順は箇条書きでつらつら書いてます。
実際の手順については、[Google Cloud Skills Boost](https://www.cloudskillsboost.google/)のラボの手順を参照してください。

クエスト「[Security & Identity Fundamentals](https://www.cloudskillsboost.google/quests/40)」の6つめのラボです。
SkillBoostの始め方は記事「[GCP スキルバッジをもらおう　1Google Cloud Skill Boostをはじめよう](https://qiita.com/orange-tora/items/57d5fe3486f4c7e1a58a)」をどうぞ。

:::note info
この記事は「<a href="https://qiita.com/advent-calendar/2021/gcp-skill-boost-sif">GCP スキルバッジをもらおう！　〜Security & Identity Fundamentals Advent Calendar 2021</a>」の一部として公開しています。
２５日にスキルバッジが獲得できるペースで公開していきます。
:::

##ラボの情報
ラボの名前：[
Getting Started with Cloud KMS](https://www.cloudskillsboost.google/focuses/1713?parent=catalog)
所要時間：30分　レベル：Fundamental　必要なクレジット:5
概要：作成したCloudStrageバケットに、KMSを使用して管理している鍵を使用して暗号化をおこない、データを保存する。

:writing_hand:Cloud　Key Management　Systemって？
Google　Cloudによるマネージドな鍵管理システム。

:writing_hand:KMSの主要な権限２つ

- `cloudkms.admin`
鍵を管理する権限。キーリングを作成し、暗号鍵を作成、変更、無効化、破壊できる。
- `cloudkms.cryptoKeyEncrypterDecrypter`
暗号化および復号する権限。暗号化および復号APIエンドポイントを呼び出すために使用される。

:writing_hand:キーリングと鍵

* 暗号鍵はキーリングに属し、キーリングはプロジェクトに属する
* その階層の上位レベルでユーザーが持つ役割と権限は子リソースに継承される
* たとえば、あるプロジェクトに対してオーナー役割を持つユーザーは、そのプロジェクトのすべてのキーリングおよび暗号鍵に対してもオーナーになる
* 同様に、あるユーザーにキーリングの cloudkms.admin 役割が付与されている場合は、そのキーリングの暗号鍵に関連する権限も付与される

##学習に役立つリンク
参考URL：
[Cloud Key Management](https://cloud.google.com/security-key-management)
[jq](https://stedolan.github.io/jq/)
[Cloud KMS のクイックスタート](https://cloud.google.com/kms/docs/quickstart)
[Google Cloud での保存時の暗号化 ](https://cloud.google.com/security/encryption/default-encryption)
KMSのRestAPIの概要：https://cloud.google.com/kms/docs/reference/rest/v1/projects.locations.keyRings.cryptoKeys
関連SDK：
[KMS](https://cloud.google.com/sdk/gcloud/reference/kms)
[REST Resource: projects.locations.keyRings.cryptoKeys](https://cloud.google.com/kms/docs/reference/rest/v1/projects.locations.keyRings.cryptoKeys)
[Gsutilのオプション（トップレベル）](https://cloud.google.com/storage/docs/gsutil/addlhelp/TopLevelCommandLineOptions)

##ラボの実施記録
###Cloud Storage バケットを作成する
バケットの名前はグローバルに一意な名前をつける必要があります。
プロジェクトIDを指定すると迷いがなくていいです。

###データをチェックアウトする
ラボの指示通りに、公開バケットからデータをダウンロードしてファイルの所在を確認します。

###Cloud KMS を有効にする
前もってプロジェクトでKMSを有効にする。

```
gcloud services enable cloudkms.googleapis.com
```

###キーリングと暗号鍵を作成する
キーリングを作成する

```
KEYRING_NAME=test CRYPTOKEY_NAME=qwiklab
gcloud kms keyrings create $KEYRING_NAME --location global
```

キーリングを使用して暗号鍵を作成する

```
gcloud kms keys create $CRYPTOKEY_NAME --location global \
      --keyring $KEYRING_NAME \
      --purpose encryption
```

###データを暗号化する
ダウンロードしたファイル（メール）をまずBase64でエンコードする。
バイナリデータをプレーンテキストとして暗号化エンドポイントに渡すため。

```
PLAINTEXT=$(cat [ファイル名] | base64 -w0)
```

`Encrypt`エンドポイントを使用して、Base64エンコードしたデータを暗号化する。（レスポンスはJSON形式）
暗号化したデータをパイプで`jq`に渡して、暗号化データ部分（`ciphertext`）を抜き出してファイル「1.encrypted」に保存する。

```
curl -v "https://cloudkms.googleapis.com/v1/projects/$DEVSHELL_PROJECT_ID/locations/global/keyRings/$KEYRING_NAME/cryptoKeys/$CRYPTOKEY_NAME:encrypt" \
  -d "{\"plaintext\":\"$PLAINTEXT\"}" \
  -H "Authorization:Bearer $(gcloud auth application-default print-access-token)"\
  -H "Content-Type: application/json"
```

暗号化したデータが復元可能かどうか、`decrypt`エンドポイントを呼び出して確認する。
上のコマンドの「1.encrypted」を指定している。
`jq .plaintext -r`の部分は`plaintext`要素を出力している。これだけだとbase64エンコードされた状態だから、パイプで`base64 -d`に出力を渡してデコードしている。

```
curl -v "https://cloudkms.googleapis.com/v1/projects/$DEVSHELL_PROJECT_ID/locations/global/keyRings/$KEYRING_NAME/cryptoKeys/$CRYPTOKEY_NAME:decrypt" \
  -d "{\"ciphertext\":\"$(cat 1.encrypted)\"}" \
  -H "Authorization:Bearer $(gcloud auth application-default print-access-token)"\
  -H "Content-Type:application/json" \
| jq .plaintext -r | base64 -d```
```

出力は、`1.`ファイルと同じ内容が出力されているはず。
暗号と複合の確認ができたので、ファイルをラボのバケットにアップロードする。


```
gsutil cp 1.encrypted gs://${BUCKET_NAME}
```

###IAM 権限を構成する

`cloudkms.admin`と`cloudkms.cryptoKeyEncrypterDecrypter`権限をラボの承認済みユーザに割り当てる。

変数に設定

```
USER_EMAIL=$(gcloud auth list --limit=1 2>/dev/null | grep '@' | awk '{print $2}')
```

まずは、`cloudkms.admin`

```
gcloud kms keyrings add-iam-policy-binding $KEYRING_NAME \
    --location global \
    --member user:$USER_EMAIL \
    --role roles/cloudkms.admin
```

つぎに、`cloudkms.cryptoKeyEncrypterDecrypter`権限

```
gcloud kms keyrings add-iam-policy-binding $KEYRING_NAME \
    --location global \
    --member user:$USER_EMAIL \
    --role roles/cloudkms.cryptoKeyEncrypterDecrypter
```

クラウドコンソールで結果を確認する。
ハンバーガー＞Security＞Key　management
また使うのでこのタブは閉じない。

###コマンドラインでデータのバックアップを作成する

ここからは、ユーザ「allen」のメールファイル全てを暗号化してバケットに保存するまでの演習。
公開バケットからデータをダウンロードする。

```
gsutil -m cp -r gs://enron_emails/allen-p .
```

ループで「allen-p」フォルダの全ファイル（メール）を暗号化する。

```
MYDIR=allen-p
FILES=$(find $MYDIR -type f -not -name "*.encrypted")
for file in $FILES; do
  PLAINTEXT=$(cat $file | base64 -w0)
  curl -v "https://cloudkms.googleapis.com/v1/projects/$DEVSHELL_PROJECT_ID/locations/global/keyRings/$KEYRING_NAME/cryptoKeys/$CRYPTOKEY_NAME:encrypt" \
    -d "{\"plaintext\":\"$PLAINTEXT\"}" \
    -H "Authorization:Bearer $(gcloud auth application-default print-access-token)" \
    -H "Content-Type:application/json" \
  | jq .ciphertext -r > $file.encrypted
done
```

暗号化したファイルを全て、ラボのバケットにアップロードする
`gsutil -m`は大量のデータをやり取りするときに使うオプション。

```
gsutil -m cp allen-p/inbox/*.encrypted 
gs://${BUCKET_NAME}/allen-p/inbox
```

クラウドコンソールで、バケットを表示してデータファイルが保管されていることを確認する。
ラボの注意書きに意もありますが、バケットは基本的に何もせずとも保管されたデータを暗号化してくれます。
今回の暗号処理はラボの演習のためにやっている。

###Cloud 監査ログを表示する

Cloudコンソールで監査アクティビティログを確認する。
ハンバーガー＞Security＞Key　management
右側の情報パネルで「Activity」を選択すると、ラボで行った操作が記録されていることを確認できる。

##お疲れさまでした
これでラボの手順は終了。
右上のスコア表示が「100/100」になっていることを確認して、「ラボを終了」を押します。