お題
前回、GCPのCloud SQLに接続するDBやユーザー、パスワードといった機密情報をapp.yaml
とは別のsecret.yaml
に分ける方法を書いた。
https://qiita.com/sky0621/items/e4ec222e50615107b405#機密情報を記載したファイルsecretyamlを用意してapp-engineデプロイ用のファイルappyamlからインクルード
ただ、このやり方だと、secret.yaml
をどうやって管理するかという問題が生じる。
今回は、この問題をGCPのCloud Key Management Service(略してKMS)を使って解消してみる。
要するに、secret.yaml
も平文でなく暗号化してGitHub管理してしまう。暗号化・復号用の鍵はGCPで管理するということ。
前提
- GCPは知っている。
以下は済んだ上での作業。
- GCPプロジェクトの作成
- Cloud SDKのインストールと初期化・認証
開発環境
# OS
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.2 LTS (Bionic Beaver)"
# Cloud SDK
$ gcloud version
Google Cloud SDK 241.0.0
実践
そもそもKMSって
公式ドキュメントやQiitaの記事もふんだんにあるので、説明は↓を見た方がいいと思う。
公式ドキュメント
その他ドキュメント
- Cloud KMS Introduction
- Cloud KMSを使ってみる
- Cloud KMS (Cloud Key Management Service) について調べたことのまとめ
- Cloud KMSでID/Passwordを暗号化し、Cloud Buildで利用する
- Cloud KMS を gcloud コマンドで試す
準備
「鍵リング」作成
↓のコマンド。任意に当たる部分は「env
」くらいかな。これは「鍵リング」の名前。
$ gcloud kms keyrings create env --location global
ERROR: (gcloud.kms.keyrings.create) FAILED_PRECONDITION: Google Cloud KMS API has not been used in this project before, or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/cloudkms.googleapis.com/overview?project=194057495083 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.
失敗。KMS APIが使えるようになってないとのこと。指定されたリンクを開くと、↓の画面(たぶん、対象のGoogleアカウント(自分のGCPプロジェクトと紐付いているやつ)でログインしてないと出ないかも?)が表示されたので「有効にする」ボタン押下。
こんな画面が表示される。
リトライ。
$ gcloud kms keyrings create env --location global
ERROR: (gcloud.kms.keyrings.create) FAILED_PRECONDITION: Google Cloud KMS API has not been used in this project before, or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/cloudkms.googleapis.com/overview?project=194057495083 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.
まだ失敗。なぜ?
・・・
あ、
$ gcloud config list
[compute]
region = asia-northeast1
zone = asia-northeast1-a
[core]
account = 【今回使うGCPプロジェクト用ではないプロジェクトのアカウント】
disable_usage_reporting = False
project = 【今回使うGCPプロジェクト用ではないプロジェクト】
Your active configuration is: [【今回使うGCPプロジェクト用ではない設定の名前】]
使うGCPプロジェクトを複数持っている場合、設定を切り替えて使うのだけど、常々確認する癖をつけておかないと、
自分が意図していないGCPプロジェクトに対して、コマンド発行してしまう。。。
※GCPプロジェクトの設定切り替えについては下記参照。
gcloud configで複数の設定を持って切り替える
というわけで、今回使うGCPプロジェクトの設定に切り替えてから再実行。
$ gcloud config configurations activate default
Activated [default].
$
$ gcloud config list
[compute]
region = asia-northeast1
zone = asia-northeast1-c
[core]
account = 【今回使うGCPプロジェクト用アカウント】@gmail.com
disable_usage_reporting = False
project = 【今回使うGCPプロジェクト】
Your active configuration is: [default]
$
$ gcloud kms keyrings create env --location global
$
エラーが出なくなった。これでKeyRing作られたってこと?
確認してみる。
出来ているもよう。
「鍵」作成
↓のコマンド。任意に当たる部分は「cloudsql-connect
」と「env
」くらいかな。
「cloudsql-connect
」は「鍵」の名前で「env
」は「鍵リング」の名前だね。
$ gcloud kms keys create cloudsql-connect --location global --keyring env --purpose encryption
$
例によってエラーなく終わったので、たぶん出来ているんだろう。
おー、できてる。
コマンドでも確認できるらしい。
$ gcloud kms list
ERROR: (gcloud.kms) Invalid choice: 'list'.
Maybe you meant:
gcloud kms keyrings list
gcloud kms keys list
gcloud kms locations list
gcloud kms keyrings add-iam-policy-binding
gcloud kms keyrings create
gcloud kms keyrings describe
gcloud kms keyrings get-iam-policy
gcloud kms keyrings remove-iam-policy-binding
gcloud kms keyrings set-iam-policy
To search the help text of gcloud commands, run:
gcloud help -- SEARCH_TERMS
間違えた。適当にコマンド打っても、ちゃんと候補らしいものを出してくれるの嬉しい。
$ gcloud kms keys list
ERROR: (gcloud.kms.keys.list) argument --location: Must be specified.
あ、ロケーションの指定が必要らしい。
$ gcloud kms keys list --location global
ERROR: (gcloud.kms.keys.list) value for field [keyRingsId] in collection [cloudkms.projects.locations.keyRings] is required but was not provided
あれ?「keyRingsId」が何か変?
あ、どの「鍵リング」の鍵の情報が見たいかを指定しないとダメなのかな。
$ gcloud kms keys list --location global --keyring env
NAME PURPOSE LABELS PRIMARY_ID PRIMARY_STATE
projects/【今回使うプロジェクト】/locations/global/keyRings/env/cryptoKeys/cloudsql-connect ENCRYPT_DECRYPT 1 ENABLED
そうらしい。
暗号化
暗号化対象ファイル
Cloud SQLに接続するためのDB名やユーザー名、パスワードといった情報は下記のsecret.yaml
に記載している。
https://github.com/sky0621/go-webapi-for-gae-study
$ pwd
/home/sky0621/work/src/go111/src/github.com/sky0621/go-webapi-for-gae-study
$
$ ls -l
合計 28
-rw-r--r-- 1 sky0621 sky0621 26 3月 31 22:15 README.md
-rw-r--r-- 1 sky0621 sky0621 43 4月 1 09:02 app.yaml
-rw-r--r-- 1 sky0621 sky0621 224 3月 31 18:36 docker-compose.yml
-rw-r--r-- 1 sky0621 sky0621 114 3月 31 23:47 go.mod
-rw-r--r-- 1 sky0621 sky0621 342 3月 31 23:47 go.sum
-rw-r--r-- 1 sky0621 sky0621 3075 4月 3 02:32 main.go
-rw-r--r-- 1 sky0621 sky0621 277 3月 31 23:15 secret.yaml
$
$ cat secret.yaml
env_variables:
# For Cloud SQL 2nd generation instances, this should be in the form of "project:region:instance".
CLOUDSQL_CONNECTION_NAME: 【今回使うGCPプロジェクト】:asia-northeast1:【インスタンス名】
CLOUDSQL_USER: 【ユーザー名】
CLOUDSQL_PASSWORD: 【パスワード】
CLOUDSQL_DATABASE: 【DB名】
※生で載せるわけにいかないので【〜〜】の部分は濁してる。
暗号化実行
secret.yaml.encrypted
という名前でsecret.yaml
を暗号化したファイルを作る。
$ gcloud kms encrypt --location global --keyring env --key cloudsql-connect --plaintext-file secret.yaml --ciphertext-file secret.yaml.encrypted
$
$ ls -l
合計 32
-rw-r--r-- 1 sky0621 sky0621 26 3月 31 22:15 README.md
-rw-r--r-- 1 sky0621 sky0621 43 4月 1 09:02 app.yaml
-rw-r--r-- 1 sky0621 sky0621 224 3月 31 18:36 docker-compose.yml
-rw-r--r-- 1 sky0621 sky0621 114 3月 31 23:47 go.mod
-rw-r--r-- 1 sky0621 sky0621 342 3月 31 23:47 go.sum
-rw-r--r-- 1 sky0621 sky0621 3075 4月 3 02:32 main.go
-rw-r--r-- 1 sky0621 sky0621 277 3月 31 23:15 secret.yaml
-rw-r--r-- 1 sky0621 sky0621 360 4月 9 09:32 secret.yaml.encrypted
$
$ cat secret.yaml.encrypted
$�!s|��XU{/����(��m^�4�v��8����ʧ���
�\T�R��ݶ�\��
G��jVb��*n��y9XW�
�N|a�XM�feG�
��<p��C1
bQls6��z�t|�QWqz�E�|e��z4?OXlFT������ �/٭�A1wЖ��,������d�h�YD���'٣C����w��bp�4�v���9t�2,�cm쫋b���>�
�6�0�-0�n�AD,����?�g����o�Kw��@����m�4��iz}��XBOa��Q�P����$�_�#�.��l0id��}o����\�q� �ΰ~?�J�k�_���W�N/_�Kĕ�#{�nH�-�9��=�Y>*�
ふむ、出来てる。
復号
復号できなきゃ意味ないので。
いったん、平文のsecret.yaml
を別名に変えておいてから、復号を試す。
$ mv secret.yaml secret.yaml.bk
$ ls -l
合計 32
-rw-r--r-- 1 sky0621 sky0621 26 3月 31 22:15 README.md
-rw-r--r-- 1 sky0621 sky0621 43 4月 1 09:02 app.yaml
-rw-r--r-- 1 sky0621 sky0621 224 3月 31 18:36 docker-compose.yml
-rw-r--r-- 1 sky0621 sky0621 114 3月 31 23:47 go.mod
-rw-r--r-- 1 sky0621 sky0621 342 3月 31 23:47 go.sum
-rw-r--r-- 1 sky0621 sky0621 3075 4月 3 02:32 main.go
-rw-r--r-- 1 sky0621 sky0621 277 3月 31 23:15 secret.yaml.bk
-rw-r--r-- 1 sky0621 sky0621 360 4月 9 09:32 secret.yaml.encrypted
$
$ gcloud kms decrypt --location global --keyring env --key cloudsql-connect --ciphertext-file secret.yaml.encrypted --plaintext-file secret.yaml
$
$ ls -l
合計 36
-rw-r--r-- 1 sky0621 sky0621 26 3月 31 22:15 README.md
-rw-r--r-- 1 sky0621 sky0621 43 4月 1 09:02 app.yaml
-rw-r--r-- 1 sky0621 sky0621 224 3月 31 18:36 docker-compose.yml
-rw-r--r-- 1 sky0621 sky0621 114 3月 31 23:47 go.mod
-rw-r--r-- 1 sky0621 sky0621 342 3月 31 23:47 go.sum
-rw-r--r-- 1 sky0621 sky0621 3075 4月 3 02:32 main.go
-rw-r--r-- 1 sky0621 sky0621 277 4月 9 09:41 secret.yaml
-rw-r--r-- 1 sky0621 sky0621 277 3月 31 23:15 secret.yaml.bk
-rw-r--r-- 1 sky0621 sky0621 360 4月 9 09:32 secret.yaml.encrypted
$
$ cat secret.yaml
env_variables:
# For Cloud SQL 2nd generation instances, this should be in the form of "project:region:instance".
CLOUDSQL_CONNECTION_NAME: 【今回使うGCPプロジェクト】:asia-northeast1:【インスタンス名】
CLOUDSQL_USER: 【ユーザー名】
CLOUDSQL_PASSWORD: 【パスワード】
CLOUDSQL_DATABASE: 【DB名】
※生で載せるわけにいかないので【〜〜】の部分は濁してる。
うん、OKだね。
まとめ
ひとまず機密情報の暗号化と復号の確認はできた。これで、環境別の機密情報も暗号化してGitHubに載せられる。
ただ、CI/CDのこと考えたら、このままじゃダメなので、次は、Cloud Buildと絡めたり、Terraformと絡めたりの方法を調べてみようか。