【Google Cloud Platformの使い方】GCP のCloud Buildでファイルを暗号化

今日は自分のサーバ用に、
- github にソースコードを置いてある
- CloudBuild と連携して、github にpush すると自動的にDocker image が build されて、Google Cloud Registry に push される
- github に置いてあるコードにはパスワードを乗せたくないが、Docker image では使う

ということを実現できたので、メモします。Google のCloud KMS (Key Management Service)を使います。Google だけなので他では使えないのかもしれませんが、とりあえず動いたのでメモします。

## はじめに

基本的に

- [鍵を作成して暗号化と復号化する手順の解説](https://cloud.google.com/kms/docs/quickstart?hl=ja)
- [Cloud Build で使うときの解説]
(https://cloud.google.com/cloud-build/docs/securing-builds/use-encrypted-secrets-credentials?hl=ja)

を読んで流れを理解すればできると思います。（自分はそうでした。）

はまりポイントとしては、ローカルでは暗号化と復号化できてもCloud Build ではできず、それは権限の付与ができていなかったことがありました。それくらいかな。

## 暗号化と復号化(KMS)

### 鍵の用意

KMSでKeyRing と Keyの２つを用意します。KeyRing にいくつものKeyが登録される構造になっています。それぞれに暗号化復号化などの権限をserviceに付与できるようです。

最初にkey ring を作成し、そのkey ring に属する鍵を作成します。

```[shell]
$ gcloud kms keyrings create ${_keyring_name} --location=global
$ gcloud kms keys create ${_key_name} --location=global --keyring=${_keyring_name} --purpose=encryption
```

鍵ができたことを確認できます。

```
$ gcloud kms keys list --location global --keyring $_keyring_name
```

ここまでの内容は実はconsole.google.cloud.com からも操作ができ、じつはそのほうが便利かもしれません。「セキュリティ」から「暗号鍵」を選択すると辿り着けます。下記の図だと一つのKeyring に2つのkey が登録されています。（塗りつぶしが汚くてすみません。。。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294040/3d16b178-f6f6-8ffc-d3fb-2bd26f65e430.png)

### ファイルを暗号化する

このkey を用いてパスワードの書かれたファイルやGCP のcredential key (json file)を暗号化します。例えば、login_password というファイル名だったとします。

```
PLAIN_FILE="login_password"
ENC_FILE=$PLAIN_FILE".enc"
gcloud kms encrypt --plaintext-file=${PLAIN_FILE} --ciphertext-file=${ENC_FILE} --location=global --keyring=${_keyring_name} --key=${_key_name}
```


を実行すると、login_password.enc が作成されます。この暗号化されたファイルを git repository に置きます。

### 復号化の動作確認

暗号化されたパスワードファイルは、git repository から取り出されて自動的にDocker build される直前に解凍して使用します。しかし、ここでは動作確認のため、ローカルの環境で復号化してもとに戻ることを確認できます。

```
_enc_file="login_password.enc"
_palin_file="login_password"
gcloud kms decrypt --ciphertext-file=${_enc_file} \
       --plaintext-file=${_plain_file} \
       --location=global --keyring=keyring-mgnss --key=key-mgnss
```
でもとの同じファイルが復元されているはずです。

### 鍵の削除

まだどのような使い方をするのか理解できていないのですが、tutorial にも書かれている通り、鍵を削除することができます。鍵にはLabel や Version という属性があり、削除するときにはVersion を指定する必要があります。そのため、まず鍵のVersion を確認します。

```
gcloud kms keys versions list --location global --keyring $_keyring_name --key $_key_name
```

このときのVersion をもとに削除します。

```
gcloud kms keys versions destroy $_key_version --location global --keyring $_keyring_name --key $_key_name
```

# Cloud Build 

さて、今
- KMSの鍵は有効である
- 復号化された（つまり普通のテキストファイルの）ファイルで動作するDocker build できるファイル群がある
- 暗号化されたファイルをgithub にある

という状態だとします。

### Cloud Build の設定

まず、github のrepository との連携を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294040/8280131c-cbb6-71a7-b8b7-526b2d2467ce.png)
トリガーを作成します。ビルドの構成では cloudbuild.yaml を使用します。自分はrepository のトップディレクトではなく、server/gcp というディレクトリにDocker で使用する一式を置いてあるので、ファイルの場所はこのようになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294040/743ba6c6-22b7-86b8-b6ca-2f8c7ada4c5d.png)

### 権限の付与

解説だと暗号鍵の設定から行うように書かれていましたが、自分が行ったときはなぜか有効になりませんでした。なので、じばり「ＩＡＭと管理」の「ＩＡＭ」から行いました。

Cloud Build のAPIを有効にしただけだと、ロールが「Cloud Build サービスアカウント」だけとなっている ...@cloudbuild.serviceaccount.com があると思います。円ぷつまーくをクリックして編集を行い、ロールに「クラウドＫＭＳ」の「暗号鍵の復号化」を追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294040/22b2ed20-8d45-2538-f09b-f5e1b3de443b.png)


### cloudbuild.yaml の実装

このYAMLの書き方は私は詳しくないのですが、とりあえずstep ごとに実行するコマンドを書いていけば動いています。

```yaml
steps:

# decrypt
- name: 'gcr.io/cloud-builders/gcloud'
  args: [ 'kms', 'decrypt', '--ciphertext-file=your_deploy_dir/login_password.enc', '--plaintext-file=your_deploy_dir/login_password', '--location=global', '--keyring=your_keyring', '--key=your_key']

# build docker image
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-t', 'asia.gcr.io/your_project/your_server', '-f', 'your_deploy_dir/Dockerfile', './your_deploy_dir']
  timeout: 500s

# push docker image to registry
- name: 'gcr.io/cloud-builders/docker'
  args: ['push', 'asia.gcr.io/your_project/your_server']
```

あとは、普通にgithub に git push すると、自動的にCloud Build のtrigger が発動して自動的にbuild ができます。

### おわりに

動いたときは割と達成感があったのですが、メモとしては地味になってしまいました。
まだまだいろいろ深堀りや改良はできそうで、

- 環境変数の暗号化の利用方法
- 鍵のVersion の利用
- 費用の確認（抑える方法？）

については宿題かもしれません。。。

(2020/05/03)