【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 だけなので他では使えないのかもしれませんが、とりあえず動いたのでメモします。

はじめに

基本的に

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

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

暗号化と復号化(KMS)

鍵の用意

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

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

$ 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 が登録されています。(塗りつぶしが汚くてすみません。。。)

ファイルを暗号化する

この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 との連携を設定します。

トリガーを作成します。ビルドの構成では cloudbuild.yaml を使用します。自分はrepository のトップディレクトではなく、server/gcp というディレクトリにDocker で使用する一式を置いてあるので、ファイルの場所はこのようになっています。

権限の付与

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

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

cloudbuild.yaml の実装

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

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)