Files
homelab-infra/infrastructure/openbao/terraform/auth.tf
T
panxiao81 e0e629794b
yaml / yaml (pull_request) Successful in 17s
terraform / validate (pull_request) Successful in 49s
为 sandbox 接入 OpenBao External Secrets
2026-09-18 17:34:53 +00:00

92 lines
3.7 KiB
Terraform

# OIDC auth (human logins via Authelia).
#
# SCOPE NOTE: only the auth MOUNT and the ROLE are managed here. The backend
# CONFIG (auth/oidc/config) is intentionally left to ../ansible because it
# carries `oidc_client_secret`. Terraform cannot read that value back from the
# API, so managing it here would (a) force the plaintext secret into
# terraform.tfstate and (b) produce a perpetual diff. Ansible already holds it
# in an ansible-vault file.
resource "vault_auth_backend" "oidc" {
type = "oidc"
path = "oidc"
}
resource "vault_jwt_auth_backend_role" "admin" {
backend = vault_auth_backend.oidc.path
role_name = "admin"
role_type = "oidc"
user_claim = "preferred_username"
bound_audiences = ["openbao"]
# Only members of the AD group vault-admins get the admin policy.
bound_claims = {
groups = "vault-admins"
}
groups_claim = "groups"
oidc_scopes = ["profile", "email", "groups"]
allowed_redirect_uris = [
"https://bao.ad.ddupan.top:8200/ui/vault/auth/oidc/oidc/callback", # web UI
"http://localhost:8250/oidc/callback", # CLI login
]
token_policies = ["admin"]
token_ttl = 3600
token_max_ttl = 0
}
# ── Kubernetes auth: the External Secrets Operator ─────────────────────────
# The BACKEND itself (auth/kubernetes/config) is NOT managed here — it needs the
# cluster CA and a long-lived reviewer JWT, which is key material Terraform must
# not hold. That stays in ../ansible (openbao_bootstrap/tasks/auth_kubernetes.yml),
# per the ownership split in CLAUDE.md. A ROLE is pure API config, so it lives here.
#
# This is what makes the operator credential-less: it presents its own
# ServiceAccount JWT, bao verifies it via the cluster's TokenReview API, and
# returns a short-lived token carrying only the external-secrets policy.
resource "vault_kubernetes_auth_backend_role" "external_secrets" {
backend = "kubernetes"
role_name = "external-secrets"
# Must match serviceAccount.name / namespace in
# ../../../platform/external-secrets/values.yaml and the serviceAccountRef in
# ../../../platform/external-secrets/clustersecretstore.yaml.
bound_service_account_names = ["external-secrets"]
bound_service_account_namespaces = ["external-secrets"]
token_policies = [vault_policy.external_secrets.name]
# Short-lived on purpose: ESO re-authenticates as needed, so there is no value
# in a long TTL and every extra hour is a longer-lived credential in memory.
token_ttl = 3600
}
# A Kubernetes auth mount can validate identities from only the API server it is
# configured against. The sandbox cluster therefore cannot reuse auth/kubernetes,
# whose TokenReview endpoint belongs to homelab.
resource "vault_auth_backend" "sandbox_kubernetes" {
type = "kubernetes"
path = "kubernetes-sandbox"
}
resource "vault_kubernetes_auth_backend_config" "sandbox" {
backend = vault_auth_backend.sandbox_kubernetes.path
kubernetes_host = "https://10.60.0.13:6443"
kubernetes_ca_cert = file("${path.module}/certs/sandbox-kubernetes-ca.crt")
disable_local_ca_jwt = true
# Deliberately omit token_reviewer_jwt. OpenBao uses the login JWT for
# TokenReview; the sandbox external-secrets ServiceAccount is bound only to
# system:auth-delegator and all issued JWTs remain short-lived.
}
resource "vault_kubernetes_auth_backend_role" "sandbox_external_secrets" {
backend = vault_auth_backend.sandbox_kubernetes.path
role_name = "external-secrets"
bound_service_account_names = ["external-secrets"]
bound_service_account_namespaces = ["external-secrets"]
token_policies = [vault_policy.sandbox_external_secrets.name]
token_ttl = 3600
}