これは何?
今のプロジェクトでterraform運用を主導しているのですが、terraformで利用する秘匿情報(DBパスワード等)はBitwardenに格納していました。
これをGCP Secret Managerに移管したら結構良いことがあったという話です。
それまでの運用
- シークレットは各環境別で分け、Bitwardenに格納
- ローカルに
secret.variable.tf
などの名前でシークレットファイルを作成し、Bitwardenからコピペしてきて利用 - シークレットファイルはgitignoreしてプッシュしないように運用
SecretManagerに移管した理由
Bitwardenのままだと、terraformを触るメンバーが増えた時に辛かったからです。
- Bitwardenからコピペする作業が発生することによって
- メンバーが増えた時の説明(オンボーディング)がダルい
- Bitwardenでシークレットを更新すると、メンバー全員にローカル更新するよう呼びかける必要がある
- Bitwardenだとバージョニングができず、管理上よくない
- 誤って誰かがシークレットファイルをGitリモートプッシュしてしまうリスク
コード
SecretManagerから最新バージョンの値をdataとして取得してきて、ローカル変数にまとめて格納します。
# Terraformで利用するシークレット
resource "google_secret_manager_secret" "terraform_secrets" {
secret_id = "TERRAFORM_GCP"
replication {
automatic = true
}
}
# シークレットから最新バージョンを取得する設定
data "google_secret_manager_secret_version" "gcp_secrets" {
secret = google_secret_manager_secret.terraform_secrets.id
version = "latest"
}
# シークレットの値をローカル変数に格納
locals {
db-pass-1 = jsondecode(data.google_secret_manager_secret_version.gcp_secrets.secret_data)["db-password-1"]
db-pass-2 = jsondecode(data.google_secret_manager_secret_version.gcp_secrets.secret_data)["db-password-2"]
}
上では説明の都合上、ローカル変数名(db-pass-1)・Secretキー名(db-root-password-1)で異なる名前にしていますが、実際は普通に一緒にした方がいいです。
※ 上記tfを一気にapplyすると、SecretManagerキーだけ作成されてバージョン(中身)がなく参照エラーになるので、キーとバージョンをあらかじめ作成しておき terraform import
するなど必要です。
SecretManagerシークレットには、手動で下記のようにjson形式で値を格納して最新バージョンとします。
{
"db-password-1" : "password1",
"db-password-2" : "password2",
}
あとは、普通にローカル変数として利用します。
resource "google_sql_user" "user-1" {
instance = "test-instance"
host = ""
name = "user-1"
password = local.db-pass-1
}
別解として下記の通り、ローカル変数を介さず直接secretデータを入れ込めます。
ただ、ローカル変数で定義しておいた方が、シークレットがまとまって見やすいと思います。
password = jsondecode(data.google_secret_manager_secret_version.gcp_secrets.secret_data)["db-password-1"]