LoginSignup
10
7

More than 5 years have passed since last update.

Cloud Key Management Service (KMS) チュートリアル

Last updated at Posted at 2019-04-09

お題

前回、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の記事もふんだんにあるので、説明は↓を見た方がいいと思う。

公式ドキュメント

その他ドキュメント

準備

「鍵リング」作成

↓のコマンド。任意に当たる部分は「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プロジェクトと紐付いているやつ)でログインしてないと出ないかも?)が表示されたので「有効にする」ボタン押下。

screenshot-console.developers.google.com-2019.04.08-09-47-58.png

こんな画面が表示される。

screenshot-console.developers.google.com-2019.04.09-08-32-44.png

リトライ。

$ 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作られたってこと?
確認してみる。

screenshot-console.cloud.google.com-2019.04.09-08-54-52.png

screenshot-console.cloud.google.com-2019.04.09-08-56-50.png

出来ているもよう。

「鍵」作成

↓のコマンド。任意に当たる部分は「cloudsql-connect」と「env」くらいかな。
cloudsql-connect」は「鍵」の名前で「env」は「鍵リング」の名前だね。

$ gcloud kms keys create cloudsql-connect --location global --keyring env --purpose encryption
$

例によってエラーなく終わったので、たぶん出来ているんだろう。

screenshot-console.cloud.google.com-2019.04.09-09-04-27.png

おー、できてる。
コマンドでも確認できるらしい。

$ 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と絡めたりの方法を調べてみようか。

10
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
7