[infra] Migrate Terraform state from local SOPS to PostgreSQL backend
Two-tier state architecture: - Tier 0 (infra, platform, cnpg, vault, dbaas, external-secrets): local state with SOPS encryption in git — unchanged, required for bootstrap. - Tier 1 (105 app stacks): PostgreSQL backend on CNPG cluster at 10.0.20.200:5432/terraform_state with native pg_advisory_lock. Motivation: multi-operator friction (every workstation needed SOPS + age + git-crypt), bootstrap complexity for new operators, and headless agents/CI needing the full encryption toolchain just to read state. Changes: - terragrunt.hcl: conditional backend (local vs pg) based on tier0 list - scripts/tg: tier detection, auto-fetch PG creds from Vault for Tier 1, skip SOPS and Vault KV locking for Tier 1 stacks - scripts/state-sync: tier-aware encrypt/decrypt (skips Tier 1) - scripts/migrate-state-to-pg: one-shot migration script (idempotent) - stacks/vault/main.tf: pg-terraform-state static role + K8s auth role for claude-agent namespace - stacks/dbaas: terraform_state DB creation + MetalLB LoadBalancer service on shared IP 10.0.20.200 - Deleted 107 .tfstate.enc files for migrated Tier 1 stacks - Cleaned up per-stack tiers.tf (now generated by root terragrunt.hcl) [ci skip] Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f538115c43
commit
e80b2f026f
360 changed files with 844 additions and 302747 deletions
|
|
@ -465,6 +465,27 @@ resource "vault_kubernetes_auth_backend_role" "openclaw" {
|
|||
token_period = 777600 # periodic: auto-renews indefinitely
|
||||
}
|
||||
|
||||
# --- Terraform State Policy & Role (Claude Agent) ---
|
||||
|
||||
resource "vault_policy" "terraform_state" {
|
||||
name = "terraform-state"
|
||||
policy = <<-EOT
|
||||
path "database/static-creds/pg-terraform-state" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
EOT
|
||||
}
|
||||
|
||||
resource "vault_kubernetes_auth_backend_role" "terraform_state" {
|
||||
backend = vault_auth_backend.kubernetes.path
|
||||
role_name = "terraform-state"
|
||||
bound_service_account_names = ["default"]
|
||||
bound_service_account_namespaces = ["claude-agent"]
|
||||
token_policies = [vault_policy.terraform_state.name]
|
||||
token_ttl = 518400 # 6d (staggered from others: ci=7d, eso=10d, woodpecker=8d, openclaw=9d)
|
||||
token_period = 518400 # periodic: auto-renews indefinitely
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Database Secrets Engine — Static Password Rotation
|
||||
# =============================================================================
|
||||
|
|
@ -501,7 +522,8 @@ resource "vault_database_secret_backend_connection" "postgresql" {
|
|||
allowed_roles = [
|
||||
# "pg-trading", # Commented out 2026-04-06 - trading-bot disabled
|
||||
"pg-health", "pg-linkwarden",
|
||||
"pg-affine", "pg-woodpecker", "pg-claude-memory"
|
||||
"pg-affine", "pg-woodpecker", "pg-claude-memory",
|
||||
"pg-terraform-state"
|
||||
]
|
||||
|
||||
postgresql {
|
||||
|
|
@ -631,6 +653,14 @@ resource "vault_database_secret_backend_static_role" "pg_claude_memory" {
|
|||
rotation_period = 604800
|
||||
}
|
||||
|
||||
resource "vault_database_secret_backend_static_role" "pg_terraform_state" {
|
||||
backend = vault_mount.database.path
|
||||
db_name = vault_database_secret_backend_connection.postgresql.name
|
||||
name = "pg-terraform-state"
|
||||
username = "terraform_state"
|
||||
rotation_period = 604800
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Kubernetes Secrets Engine — Dynamic K8s Credentials
|
||||
# =============================================================================
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
# Generated by Terragrunt. Sig: nIlQXj57tbuaRZEa
|
||||
locals {
|
||||
tiers = {
|
||||
core = "0-core"
|
||||
cluster = "1-cluster"
|
||||
gpu = "2-gpu"
|
||||
edge = "3-edge"
|
||||
aux = "4-aux"
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue