feat(iam): automate Authentik OAuth provisioning + create admin user rock

Adds k8s/security/iam/authentik-provision-job.yaml - a PostSync hook Job
(reruns every ArgoCD sync via hook-delete-policy: BeforeHookCreation) that
replaces the never-migrated setup_talos_iam.sh / provision_oidc.py workflow
(both referenced helmfile + a Python script that no longer exists in this
repo - OAuth was never actually provisioned since the ArgoCD migration).

Idempotently creates:
  - Custom 'groups' OAuth2 scope mapping (Authentik doesn't ship one by
    default; required for ArgoCD's RBAC groups claim and Grafana's
    role_attribute_path, both of which read a groups claim from the token).
  - Groups: homelab-admins (is_superuser), grafana-admins.
  - User 'rock', member of both groups above - gets full Authentik superuser
    access, ArgoCD role:admin via the existing
     RBAC policy in argocd-values.yaml, and
    Grafana Admin role via role_attribute_path. Password generated once,
    stored in iam/rock-credentials (never rotated on re-run).
  - OAuth2 providers + Applications for grafana, minio, forgejo, argocd.
    Client secrets read from existing Secrets (grafana-oidc, minio-oidc) or
    generated once and written out (forgejo-oidc, argocd's oidc-secret).
  - PolicyBinding of homelab-admins -> every Application, guaranteeing rock
    access regardless of each app's default visibility.

Also fixes forgejo-values.yaml: oauth2.CLIENT_ID was set but CLIENT_SECRET
was missing entirely (oauth2 login could never have worked). Added via
extraEnv -> GITEA__oauth2__CLIENT_SECRET sourced from the new forgejo-oidc
Secret, since the oauth2: values map can't reference a Secret inline.

RBAC: dedicated ServiceAccount + ClusterRole (secrets get/list/create/update/
patch only) bound via namespace-scoped RoleBindings in iam/cicd/argocd/
logging/storage - the only 5 namespaces this job ever touches, and the only
resource type it ever touches.

NOTE: MinIO's OIDC env vars were removed from minio-tenant.yaml earlier
(blocked IAM init because the provider/app didn't exist yet -> 404 on
discovery). Now that this job creates them, re-adding MinIO's OIDC config is
a safe follow-up in a separate change.
This commit is contained in:
Story Crater Bot
2026-07-21 16:31:03 -07:00
parent 1dd261bb25
commit d602ed8c78
2 changed files with 509 additions and 0 deletions
+17
View File
@@ -52,6 +52,12 @@ gitea:
OPENID_CONNECT_DISCOVERY_URL: https://authentik.riotpiao.com/application/o/forgejo/.well-known/openid-configuration
CLIENT_ID: forgejo
AUTO_DISCOVER_URL: https://authentik.riotpiao.com/application/o/forgejo/.well-known/openid-configuration
# CLIENT_SECRET was missing entirely before - oauth2 login could never
# have worked. Value comes from the forgejo-oidc Secret (created by the
# authentik-provision PostSync hook, see k8s/security/iam/authentik-
# provision-job.yaml) via extraEnv below, since this oauth2: map is
# rendered directly into plain env vars and can't reference a Secret
# inline the way envFromSecret/extraEnv can.
cache:
ADAPTER: redis
HOST: redis://forgejo-redis.cicd.svc:6379/0
@@ -139,6 +145,17 @@ tolerations:
# trusting both the standard Mozilla bundle and our homelab CA.
# Required for OIDC: Forgejo fetches Authentik's discovery endpoint which
# presents a cert signed by homelab-ca.
# CLIENT_SECRET for the oauth2 block above - gitea's own config map (oauth2:)
# can only hold plain values, so the Secret-backed one is injected as
# GITEA__oauth2__CLIENT_SECRET, following the chart's standard
# GITEA__<section>__<KEY> env-var-to-ini-config convention.
extraEnv:
- name: GITEA__oauth2__CLIENT_SECRET
valueFrom:
secretKeyRef:
name: forgejo-oidc
key: CLIENT_SECRET
extraVolumes:
- name: homelab-ca
configMap: