HashiCorp VaultのGCPシークレットエンジンを試してみたので導入方法とサービスアカウント作るところまでを備忘録としてメモ。
TL;DR
- Terraform module registryを使えばTerraformで一瞬でGCP上にVault環境が作成できる。
- GCP シークレットエンジンを使えばVault経由でコマンド一発で一時的なサービスアカウントを作成できる。
事前準備
VaultではCloud KMSを使用してシークレットを暗号化する。
シークレット保管方法について詳細はこちらを参照。
シークレットを使用するユーザーとサービス、シークレットを管理するユーザーとサービスは、2 つのプロジェクトと 2 人のユーザーに分けて確実に職掌分散することをおすすめします。あるプロジェクトは Cloud KMS を使用して鍵を管理し、もう 1 つのプロジェクトは Cloud Storage バケットを使用してシークレットを保存します。
事前準備としてVault専用プロジェクト、サービスアカウントを作成しておく。
IAMサービス有効化
$ export GOOGLE_CLOUD_PROJECT='dkuji-vault'
cloudresourcemanager.googleapis.com \
iam.googleapis.com
サービスアカウント作成
$ gcloud iam service-accounts create vault-tester \
--display-name vault-tester \
--project "${GOOGLE_CLOUD_PROJECT}"
Created service account [vault-tester].
IAMポリシー適用
$ gcloud projects add-iam-policy-binding "${GOOGLE_CLOUD_PROJECT}" \
--member "serviceAccount:vault-tester@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
--role "roles/owner"
キー作成
$ gcloud iam service-accounts keys create credential.json \
--iam-account "vault-tester@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com"
TerraformでGCE、KMS、GCS、NAT、GCLBを作成
こちらのTerraform module registryを使用し作成する。
module "vault" {
source = "terraform-google-modules/vault/google"
version = "1.0.0"
project_id = "dkuji-vault"
region = "us-central1"
kms_keyring = "vault"
#kms_keyring = "${var.kms_keyring}"
kms_crypto_key = "vault-init"
vault_machine_type = "g1-small"
}
provider "google" {
project = "dkuji-vault"
credentials = "${file("credential.json")}"
}
$ terraform init
$ terraform apply
Vaultサーバに接続
vaultアドレス、証明書を環境変数で指定。
アドレスはoutputから、証明書はterraform apply実行時にカレントディレクトリに作成されたものを指定。
$ export VAULT_ADDR="`terraform output --module=vault vault_addr`
$ export VAULT_CACERT="$(pwd)/ca.crt"
正常にvaultサーバに接続できることを確認。
$ vault status
Key Value
--- -----
Recovery Seal Type gcpckms
Initialized false
Sealed true
Total Recovery Shares 0
Threshold 0
Unseal Progress 0/0
Unseal Nonce n/a
Version n/a
HA Enabled true
アンシール
Vaultサーバを初期化。標準出力にトークンが出力されるので必ずメモしておく。
5つのリカバリキーを発行し、アンシールのしきい値を3で設定。
$ vault operator init \
-recovery-shares 5 \
-recovery-threshold 3
Recovery Key 1: **********
Recovery Key 2: **********
Recovery Key 3: **********
Recovery Key 4: **********
Recovery Key 5: **********
Initial Root Token: **********
Success! Vault is initialized
Recovery key initialized with 5 key shares and a key threshold of 3. Please
securely distribute the key shares printed above.
Vaultサーバにログイン。先程発行されたRootトークンを指定。
$ vault login
Token (will be hidden):
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.
$ vault status
Key Value
--- -----
Recovery Seal Type shamir
Initialized true
Sealed false
Total Recovery Shares 5
Threshold 3
Version 1.0.3
Cluster Name vault-cluster-4936f388
Cluster ID b00b993f-4571-cc02-06da-31e24767d0e4
HA Enabled true
HA Cluster https://xx.xx.xx.xx:8201
HA Mode active
GCPシークレットエンジンを有効化
$ vault secrets enable gcp
$ vault secrets list
Path Type Accessor Description
---- ---- -------- -----------
cubbyhole/ cubbyhole cubbyhole_919d48c5 per-token private secret storage
gcp/ gcp gcp_45cb8da8 n/a
identity/ identity identity_b29994dd identity store
secret/ kv kv_ee02181a key/value secret storage
sys/ system system_08a62e9a system endpoints used for control, policy and debugging
パスgcp/config
に最初に作成したサービスアカウントキーを指定。このIAMアカウントを使用してこれ以降のアカウントが作成される。
$ vault write gcp/config credentials=@credential.json
サービスアカウントを作成してみる。
$ vault write gcp/roleset/token-test \
project="${GOOGLE_CLOUD_PROJECT}" \
secret_type="access_token" \
token_scopes="https://www.googleapis.com/auth/cloud-platform" \
bindings=-<<EOF
resource "//cloudresourcemanager.googleapis.com/projects/${GOOGLE_CLOUD_PROJECT}" {
roles = ["roles/viewer"]
}
EOF
$ vault write gcp/roleset/key-test \
project="${GOOGLE_CLOUD_PROJECT}" \
secret_type="service_account_key" \
bindings=-<<EOF
resource "//cloudresourcemanager.googleapis.com/projects/${GOOGLE_CLOUD_PROJECT}" {
roles = ["roles/viewer"]
}
EOF
WebコンソールからIAMを確認してみると、作成された。


サービスアカウントキーを作成
先程作成したアカウントをreadすると、サービスアカウントキー、トークンが作成される。
ちなみにこれで作成したアカウントは一時的なものであり、一定期間で自動的にクリーンアップされる。
$ vault read gcp/token/token-test
Key Value
--- -----
expires_at_seconds 1559478504
token ***********************************************
token_ttl 59m59s
$ vault read gcp/key/key-test
Key Value
--- -----
lease_id gcp/key/key-test/ahigW7iLat8RDEmY9qtCDChe
lease_duration 767h59m59s
lease_renewable true
key_algorithm KEY_ALG_RSA_2048
key_type TYPE_GOOGLE_CREDENTIALS_FILE
private_key_data ***********************************************
おわりに
VaultのGCPシークレットエンジンを使ってサービスアカウントを作成まで特に問題なくできた。
サービスアカウントは基本的にはTerraformで管理するが、検証等で一時的にしようするアカウントに限りVaultから作成して終わったらそのまま放置し自動的に破棄(Terraformでも管理しない)みたいな使い方になるのかなと思った。
参考
https://www.vaultproject.io/docs/secrets/gcp/index.html
https://github.com/hashicorp/vault-plugin-secrets-gcp