11 KiB
noble_authentik — Authentik + OIDC for the noble stack
Installs Authentik (Helm goauthentik/authentik) as the cluster IdP, oauth2-proxy as an OIDC client to Authentik for Traefik ForwardAuth (Prometheus, Alertmanager, Longhorn UI), and re-applies Helm values so Argo CD, Grafana, and Headlamp use native OIDC to Authentik (not HTTP BasicAuth).
Enable
- Copy repository
.env.sampleto.envand set everyNOBLE_AUTHENTIK_*variable (see comments there). - Set
noble_authentik_install: trueinansible/inventory/group_vars/all.yml(or pass-e noble_authentik_install=true). - Run
ansible-playbook playbooks/noble.yml --tags authentik(or a fullnoble.yml) fromansible/with a workingKUBECONFIG.
noble_authentik runs after noble_platform so Grafana / Headlamp / Prometheus exist before SSO Helm upgrades.
Variables
See defaults/main.yml. Hostnames default to auth.apps.noble.lab.pcenicni.dev and oauth2.apps.noble.lab.pcenicni.dev. noble_authentik_ensure_admin_ui_access (default true) re-applies authentik Admins superuser membership via the worker on each --tags authentik run so the admin UI keeps working under 2026+ RBAC.
IdP configuration
When noble_authentik_configure_idp is true, Ansible creates/updates OAuth2 providers and applications for argocd, grafana, headlamp, and oauth2-proxy using either the worker ORM path (default noble_authentik_oidc_provision_via: worker: kubectl exec + ak shell + files/worker_upsert_oauth_oidc.py, which avoids 2026+ REST 403 on GET …/providers/oauth2/**) or the REST-only path (noble_authentik_oidc_provision_via: rest**: files/configure_authentik.py needs a token that can list/patch OAuth2 providers). With the worker path and a bootstrap email, it also runs files/worker_add_bootstrap_user_groups.py so User.groups.add does not depend on **GET …/core/users/**. It then runs configure_authentik.py with AUTHENTIK_SKIP_OIDC_REST / AUTHENTIK_SKIP_USER_GROUP_REST when those worker steps ran, so the script only calls ensure_group over the API (skipped when AUTHENTIK_NOBLE_*_GROUP_PK are set).
RBAC notes
- Argo CD:
noble-adminsgroup →role:admin(seeclusters/noble/bootstrap/argocd/values-authentik-oidc.yaml). - Grafana:
noble-admins→ Admin,noble-editors→ Editor (seevalues-authentik-oidc.yaml).
Troubleshooting
- oauth2-proxy shows 500 on
oauth2.apps…/oauth2/callback(logs:email in id_token (...) isn't verified): Authentik’s id_token often lacksemail_verified: truefor bootstrap users.clusters/noble/bootstrap/oauth2-proxy/values.yamlsetsinsecure-oidc-allow-unverified-emailfor the lab; otherwise verify the user’s email in Authentik, thenhelm upgrade oauth2-proxy(or--tags authentik). - Re-run
configure_authentik.pyonly by executingnoble.ymlwith--tags authentikafter fixing.env. - If Authentik API calls fail, check flows exist (slug
default-provider-authorization-implicit-consent) and TLS reachesAUTHENTIK_API_BASE. GET …/flows/instances/…→ HTTP 403 withToken invalid/expired: the bootstrap API token is not accepted yet (common right after install: worker still creating it) orNOBLE_AUTHENTIK_BOOTSTRAP_TOKENin.envdoes not match the value Helm applied. Re-run--tags authentik(the role waits forGET …/core/applications/to return 200 with your token). If you rotated the token in.envonly, run the play again so Helm picks up the new value, or mint a new API token forakadminin the admin UI.GET …/flows/instances/…→ HTTP 403 with permission errors (Authentik 2026+ RBAC): the bootstrap API token often cannot view flows. The role reads flow UUIDs from the worker database (kubectl exec+ak shell) whennoble_authentik_oauth_authorization_flow_pk/noble_authentik_oauth_invalidation_flow_pkare unset. The same pattern applies to/crypto/certificatekeypairs/,/propertymappings/…,/core/groups/, and the matchingnoble_authentik_*inventory variables. If a lookup fails, fixakadmin/ authentik Admins / token, or set the UUID variables manually (see below).GET …/crypto/certificatekeypairs/…→ HTTP 403 (permission): same RBAC issue as flows. Whennoble_authentik_oauth_signing_key_pkis unset, the role resolves the first CertificateKeyPair UUID from the worker DB. You can also setnoble_authentik_oauth_signing_key_pkmanually (Admin → System → Certificates).GET …/propertymappings/…→ HTTP 403 (permission): whennoble_authentik_oauth_scope_mapping_pksis unset, the role resolves ScopeMapping UUIDs from the worker DB: openid, email, profile, offline_access, and groups only if a separategroupsmapping exists (Authentik 2026.x defaults put groups inside profile only).GET …/core/groups/…→ HTTP 403 (permission): whennoble_authentik_group_pk_noble_adminsandnoble_authentik_group_pk_noble_editorsare unset, the role runsresolve_noble_group_pks.pyin the worker (get_or_createfor noble-admins / noble-editors), then passesAUTHENTIK_NOBLE_*_GROUP_PKintoconfigure_authentik.pyso it skips group list/create via REST.GET …/providers/oauth2/…→ HTTP 403 (permission): bootstrap tokens often cannot list OAuth2 providers. With the defaultnoble_authentik_oidc_provision_via: worker, the role upserts providers and applications inauthentik-workervia Django ORM (worker_upsert_oauth_oidc.py) instead ofconfigure_authentik.pyREST. Setnoble_authentik_oidc_provision_via: restonly if your API token has view_oauth2provider / provider edit permissions (e.g. a full akadmin token from the UI).GET …/core/users/…→ HTTP 403 when adding the bootstrap user to noble-admins / noble-editors: withnoble_authentik_oidc_provision_via: workerand a non-empty bootstrap email, the role runsworker_add_bootstrap_user_groups.pyin the worker (ORMUser.groups.add) and setsAUTHENTIK_SKIP_USER_GROUP_RESTsoconfigure_authentik.pydoes not call the users API for membership.- Manual flow / signing / scope / group UUIDs (optional): set
noble_authentik_oauth_authorization_flow_pkandnoble_authentik_oauth_invalidation_flow_pk(both together), optionallynoble_authentik_oauth_signing_key_pk,noble_authentik_oauth_scope_mapping_pks,noble_authentik_group_pk_noble_admins, andnoble_authentik_group_pk_noble_editors, from the admin UI or-e/group_vars;configure_authentik.pythen skips the matching REST discovery calls. /if/admin/redirects to/if/user/(lost admin panel): in 2026.x,canAccessAdminfollowsisSuperuser, which is true only when the user belongs to a group with the superuser flag (authentik Adminsby default).noble_authentik_ensure_admin_ui_access(default true) makes--tags authentikrunfiles/worker_ensure_authentik_admin_access.pyin authentik-worker (adds akadmin or the bootstrap email user to authentik Admins and forcesis_superuseron that group). Log out of Authentik (private window is fine) and sign in again. Setnoble_authentik_ensure_admin_ui_access: falseto skip. Without Ansible, you can fix it in Directory → Groups → authentik Admins (superuser flag + membership) or runak shellwith the same logic as that script.- Grafana / Headlamp / ForwardAuth “Unauthorized” or Authentik “Not found” (Authentik 2026.x): OAuth endpoints are no longer under
/application/o/<app>/oauth2/.... Use issuer discovery (Grafanaserver_urlat…/application/o/<slug>/; oauth2-proxyoidc-issuer-url; Headlamp-oidc-idp-issuer-url). Re-apply Traefik (allowCrossNamespaceso Ingresses can use Middleware inoauth2-proxy), kube-prometheus-stack, and Headlamp after updating values (e.g.ansible-playbook playbooks/noble.yml --tags authentik). - Headlamp OIDC authorize fails /
invalid_scope: Authentik often has no separategroupsScopeMapping (groups live underprofile). Defaultnoble_authentik_headlamp_oidc_scopesomitsgroups; add agroupsmapping to the provider in Authentik and setnoble_authentik_headlamp_oidc_scopesto includegroupsif you need that scope by name. - Headlamp OIDC: Authentik flashes then back at login / page refresh: Headlamp does support normal browser OAuth (redirect to Authentik and return to
/oidc-callback). If the callback fails, the UI looks like it “drops” auth. Common causes:X-Forwarded-Protonot reaching Headlamp (callback built ashttp— see Headlamp OIDC docs); Traefik ForwardAuth on the same Ingress (do not combine with native OIDC); PKCE state issues — this role defaultsnoble_authentik_headlamp_oidc_use_pkce: falsefor Authentik confidential clients (settrueingroup_varsif you need PKCE). - Headlamp UI:
/meworks but/clusters/main/version(and other K8s calls) return 401: Headlamp forwards your OIDC id_token to kube-apiserver. The API server must be configured with OIDC flags for the same issuer andoidc-client-idas Headlamp (seetalos/talconfig.yamlpatch and Kubernetes OIDC authentication). Apply regenerated Talos configs to control plane nodes, thenkubectl apply -k clusters/noble/bootstrap/headlamp(or--tags authentik) foroidc-noble-admins-clusterrolebinding.yaml. Ensure your user is in Authentik groupnoble-adminsand the id_token includes agroupsclaim if you rely on that binding. - Headlamp + Traefik ForwardAuth (
oauth2-proxy-forward-auth): Do not put ForwardAuth on the Headlamp Ingress while using native Headlamp OIDC. Auth runs on/oidc-callbackbefore Headlamp can finish the code exchange; ForwardAuth returns 401 and breaks login. Use either native OIDC (this repo’svalues-authentik-oidc.yaml) or terminate auth at oauth2-proxy only (noconfig.oidc), not both.
Fix admin access manually (worker shell, no Ansible)
kubectl exec -it deploy/authentik-worker -n authentik -- ak shell -c "from authentik.core.models import User, Group; u=User.objects.get(username='akadmin'); adm,_=Group.objects.get_or_create(name='authentik Admins', defaults={'is_superuser': True}); adm.is_superuser=True; adm.save(update_fields=['is_superuser']); u.groups.add(adm); u=User.objects.get(pk=u.pk); print('is_superuser', u.is_superuser)"
Then log out of Authentik and sign in again.