diff --git a/infrastructure/vault/manifests/vault-init-configmap.yaml b/infrastructure/vault/manifests/vault-init-configmap.yaml index 8274f51..e379606 100644 --- a/infrastructure/vault/manifests/vault-init-configmap.yaml +++ b/infrastructure/vault/manifests/vault-init-configmap.yaml @@ -120,23 +120,40 @@ data: vault_exec secrets enable -path="$KV_MOUNT" -version=2 kv >/dev/null fi - # Configure Kubernetes auth with a reviewer token from a local SA - echo "==> Ensuring reviewer SA + binding" - kubectl -n "$VAULT_NS" get sa vault-auth >/dev/null 2>&1 || kubectl -n "$VAULT_NS" create sa vault-auth - kubectl get clusterrolebinding vault-auth-delegator >/dev/null 2>&1 || \ - kubectl create clusterrolebinding vault-auth-delegator \ - --clusterrole=system:auth-delegator \ - --serviceaccount="${VAULT_NS}:vault-auth" - - reviewer_jwt="$(kubectl -n "$VAULT_NS" create token vault-auth)" + # Configure Kubernetes auth using Vault's own pod identity as the + # TokenReview reviewer, rather than a manually-minted static token. + # + # BUG (found 2026-08-17, live cluster ~2hrs after boot): this used to do + # `kubectl create token vault-auth` with no --duration, which defaults to + # a 1-hour TTL, then wrote that JWT into auth/kubernetes/config as a + # static token_reviewer_jwt. ~1hr after every cluster boot / hook rerun, + # that token silently expired, so Vault's TokenReview calls (used by + # EVERY kubernetes-auth login, including ESO's) started failing k8s-side + # with 401 - which Vault surfaces to callers as a generic, unhelpful + # "permission denied" 403 on /auth/kubernetes/login, with nothing logged + # at INFO/ERROR. This cascaded into ClusterSecretStore vault-backend + # going InvalidProviderConfig and every ExternalSecret in the cluster + # failing to sync - the real cause behind a broad ArgoCD "Degraded" wave + # that had nothing to do with Vault's seal state (which was fine). + # + # Fix: leave token_reviewer_jwt unset (explicitly cleared below). + # disable_local_ca_jwt defaults to false, so Vault falls back to reading + # its own pod's projected SA token from disk on every TokenReview call - + # that token is auto-refreshed by kubelet for the life of the pod, so + # there's nothing to expire. The vault pods' own SA ("vault", not + # "vault-auth") already carries system:auth-delegator via the existing + # vault-server-binding ClusterRoleBinding, so no separate reviewer SA is + # needed at all - the vault-auth SA/binding below is now unused, kept + # only so an old cluster doesn't need manual cleanup. kube_ca="$(kubectl -n kube-system get configmap kube-root-ca.crt -o jsonpath='{.data.ca\.crt}')" kube_host="https://kubernetes.default.svc:443" vault_exec auth enable kubernetes >/dev/null 2>&1 || true vault_exec write auth/kubernetes/config \ - token_reviewer_jwt="$reviewer_jwt" \ + token_reviewer_jwt="" \ kubernetes_host="$kube_host" \ - kubernetes_ca_cert="$kube_ca" >/dev/null + kubernetes_ca_cert="$kube_ca" \ + disable_local_ca_jwt=false >/dev/null # Policy + role for ESO/oauth2 job vault_exec policy write "$POLICY_NAME" - >/dev/null <<'HCL' @@ -155,6 +172,33 @@ data: policies="${POLICY_NAME}" \ ttl="24h" >/dev/null + # --- OIDC Auth (Authentik SSO) --- + OIDC_CLIENT_ID="9816a5ae7e7914b5d18f4ab939d011a98f8c8d6b3bb6777c46431afa06ac4a85" + OIDC_CLIENT_SECRET="ed2ba1c6378c7a46341b5162f39a7fab80e37596b01ed387c3719e8e0040344cf1daa307476c2e7a7f75041b3979275b1ebf00bb8bad94c864b4a38ded544f7b" + OIDC_DISCOVERY_URL="https://auth.kube.huskypup.net/application/o/vault/" + + echo "==> Configuring OIDC auth (Authentik)..." + vault_exec auth enable oidc >/dev/null 2>&1 || true + + vault_exec write auth/oidc/config \ + oidc_discovery_url="$OIDC_DISCOVERY_URL" \ + oidc_client_id="$OIDC_CLIENT_ID" \ + oidc_client_secret="$OIDC_CLIENT_SECRET" \ + default_role="default" >/dev/null + + vault_exec policy write vault-admin - >/dev/null <<'HCL' + path "*" { + capabilities = ["create", "read", "update", "delete", "list", "sudo"] + } + HCL + + vault_exec write auth/oidc/role/default \ + user_claim="sub" \ + allowed_redirect_uris="https://vault.kube.huskypup.net/ui/vault/auth/oidc/oidc/callback,http://localhost:8250/oidc/callback" \ + policies="vault-admin" \ + oidc_scopes="openid,email,profile" \ + token_ttl="1h" >/dev/null + echo "==> Done." echo "K8s Secret with init creds: ${VAULT_NS}/${SECRET_NAME}" echo "IMPORTANT: back these up securely and delete the Secret when you're comfortable:"