GKE: Vault values, auto-unsealing from Cloud KMS
Same chart (0.34.1) and same shape as the homelab — production mode, file storage, standalone, no HA, injector off — with one substantial difference: this Vault unseals itself. The homelab unseals with 3 of 5 Shamir keys after every restart, which was fine on an always-on VM. These nodes are spot and can be reclaimed at any hour, and a sealed Vault means every secret in the cluster is unavailable until someone notices. The trade is named rather than buried: unsealing now depends on GCP IAM rather than on people holding key shares. The seal stanza's values come from terraform output vault_seal, so Terraform and this file cannot disagree about which key is used, and no credential appears in either: the pod authenticates to KMS as its Workload Identity. That binding names exactly vault/vault, so serviceAccount.name is pinned and the GSA annotation set — miss either and Vault starts, fails to reach KMS, and stays sealed with an error that never mentions Workload Identity. Verified against the live project: the rendered seal block matches the existing key ring and key, which grant encrypt/decrypt to that service account and nothing else. Storage is 10Gi on standard-rwo. The homelab's 5Gi exists only because local-path cannot expand a bound volume; this class can. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LEsTefWWifp4ikvhHF5s6N
This commit is contained in:
co-authored by
Claude Opus 5
parent
cdc6d9167c
commit
63c243ce51
@@ -0,0 +1,91 @@
|
||||
vault:
|
||||
# GKE counterpart of helm-overrides/k8s-admin-prd-ase1/vault, same chart
|
||||
# (0.34.1) and same shape — production mode, file storage, standalone, no
|
||||
# HA — with one substantial difference: this Vault unseals itself from
|
||||
# Cloud KMS instead of by hand.
|
||||
#
|
||||
# The homelab unseals with 3 of 5 Shamir keys after every restart. That
|
||||
# was fine on an always-on VM. Here the nodes are spot and can be
|
||||
# reclaimed at any hour, and a sealed Vault means every secret in the
|
||||
# cluster is unavailable until a human notices. The trade, stated plainly:
|
||||
# unsealing now depends on GCP IAM rather than on people holding key
|
||||
# shares.
|
||||
#
|
||||
# This is a fresh install, not an adoption. Init is still a one-off manual
|
||||
# step (`vault operator init`), and with a KMS seal it returns RECOVERY
|
||||
# keys plus a root token — recovery keys cannot unseal a running Vault,
|
||||
# they exist to recover or rekey it. Keep them and the root token in a
|
||||
# password manager; they belong in neither Git nor Vault itself.
|
||||
|
||||
injector:
|
||||
enabled: false
|
||||
|
||||
server:
|
||||
# The Workload Identity binding Terraform created names exactly
|
||||
# vault/vault — this namespace and this service account name. The
|
||||
# annotation is the other half of that pair. Miss either and Vault
|
||||
# starts, fails to reach KMS, and stays sealed with a permission error
|
||||
# that does not mention Workload Identity at all.
|
||||
serviceAccount:
|
||||
create: true
|
||||
name: vault
|
||||
annotations:
|
||||
iam.gke.io/gcp-service-account: toolshed-vault@toolshed-testing-508208.iam.gserviceaccount.com
|
||||
|
||||
dataStorage:
|
||||
enabled: true
|
||||
# 10Gi rather than the homelab's 5Gi: that number exists only because
|
||||
# local-path cannot expand a bound volume. standard-rwo can expand, so
|
||||
# this is the chart default, not a constraint.
|
||||
size: 10Gi
|
||||
storageClass: standard-rwo
|
||||
|
||||
ha:
|
||||
enabled: false
|
||||
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
memory: 256Mi
|
||||
|
||||
standalone:
|
||||
enabled: true
|
||||
# `ui = true` here AND ui.enabled below are both required — the chart
|
||||
# has two separate toggles for the same thing, and setting only one
|
||||
# leaves the UI 404ing (claude.md issue #10).
|
||||
#
|
||||
# The seal stanza's values come from terraform output vault_seal, so
|
||||
# Terraform and this file cannot disagree about which key Vault
|
||||
# unseals with. No credentials appear here: the pod authenticates to
|
||||
# KMS as its Workload Identity, so there is no key file to mount,
|
||||
# rotate, or leak.
|
||||
config: |
|
||||
ui = true
|
||||
listener "tcp" {
|
||||
address = "[::]:8200"
|
||||
cluster_address = "[::]:8201"
|
||||
tls_disable = "true" # lab only - enable TLS for anything beyond local testing
|
||||
}
|
||||
storage "file" {
|
||||
path = "/vault/data"
|
||||
}
|
||||
seal "gcpckms" {
|
||||
project = "toolshed-testing-508208"
|
||||
region = "us-central1"
|
||||
key_ring = "toolshed-vault"
|
||||
crypto_key = "unseal"
|
||||
}
|
||||
|
||||
# Single host — no Tailscale here. Plain HTTP through Contour, matching
|
||||
# tls_disable above.
|
||||
ingress:
|
||||
enabled: true
|
||||
ingressClassName: contour
|
||||
hosts:
|
||||
- host: "vault.35.238.248.203.nip.io"
|
||||
paths: []
|
||||
|
||||
ui:
|
||||
enabled: true
|
||||
Reference in New Issue
Block a user