今日は自分のサーバ用に、
- github にソースコードを置いてある
- CloudBuild と連携して、github にpush すると自動的にDocker image が build されて、Google Cloud Registry に push される
- github に置いてあるコードにはパスワードを乗せたくないが、Docker image では使う
ということを実現できたので、メモします。Google のCloud KMS (Key Management Service)を使います。Google だけなので他では使えないのかもしれませんが、とりあえず動いたのでメモします。
はじめに
基本的に
- 鍵を作成して暗号化と復号化する手順の解説
- [Cloud Build で使うときの解説]
(https://cloud.google.com/cloud-build/docs/securing-builds/use-encrypted-secrets-credentials?hl=ja)
を読んで流れを理解すればできると思います。(自分はそうでした。)
はまりポイントとしては、ローカルでは暗号化と復号化できても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 サービスアカウント」だけとなっている ...@cloudbuild.serviceaccount.com があると思います。円ぷつまーくをクリックして編集を行い、ロールに「クラウド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)