Kanidm: provision per-cluster OAuth2 clients + machine SAs for cluster tooling #35
Labels
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lab/iac#35
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Kanidm: provision per-cluster OAuth2 clients + machine SAs for cluster tooling
Sveltos and Argo CD both need to authenticate to remote clusters. The k8s apiserver OIDC flags (flux-clusters #11/#1522 / iac #11) will validate Kanidm tokens, so the tooling should use the same RFC 8693 flow Argo CD already uses (Kanidm SA API token → token via
kanidm-login.py), instead of per-tool static SA credentials.This is the shared prerequisite for all three cluster-auth consumers: #36 (Sveltos), #37 (Argo CD), and #29 (Vault kubernetes-auth TokenReview).
What to build
https://auth.animeteamspeak.moe/oauth2/openid/minicluster, clientIDminicluster;…/portablecluster, clientIDportablecluster) — provisioned inkanidm/oauth2.tf. Thegroups_namescope must be granted to the cluster's groups so the exchanged token'sgroups_nameclaim feeds the apiserver's--oidc-groups-claim=groups_name(no custom claim maps). Each clientID is also the exchange audience the authz-bridge requests — the exchanged id_token lands in the apiserver's own audience. (2026-09: replaces the original single sharedkubernetesclient design.)vault(Vault's TokenReview caller, #29),tofu-k8s(tofu-controller k8s root runner, #25),sveltos-<cluster>,argocd-<cluster>, and any future autonomous system (agents, homebox, sonarr) get their own Kanidm SA holding the relevant capability groups (ADR-0006: machines are just principals holding the same groups). Each SA's API token is the single long-lived credential for that actor — the only secret, held by the actor (in its kubeconfig/cluster secret), exchanged per request by the k8s-hub authz-bridge.newOAuth.sh/kanidm-login.pypattern: create the clients, scope maps, and SAs declaratively, no hand-run kanidm commands that drift. Must include the per-groupgroups_namescope-map entry for each cluster client (without it, exchanges withscope=openid groups_namefailaccess_denied— verified 2026-08-12).Design questions (resolved)
clientAuth: { clientId: kubernetes, method: clientSecretPost }with no secret is accepted (same as thevault-clipublic-client precedent, ADR-0005). The apiserver only needs JWKS + discovery; no client secret anywhere.sveltos-<cluster>,argocd-<cluster>). Per-actor revocation and per-actor audit; matches the capability-group model (ADR-0006). A machine is just a principal holding the same groups.kanidm/root (the OAuth2 clients per ADR-0005 pattern); the ~90 user-facing UI groups inkanidm/groups.tfare untouched.Resolved — Kanidm conformance (#39)
agentgateway previously rejected Kanidm's RFC 8693 response (
issued_token_type: "AccessToken"was not the standard URN). Fixed and verified (2026-08-12): Kanidm1.11.0-itt-fixemits the URN and the exchange returns 200 through agentgateway. Tracked internally, never upstreamed: #39.Acceptance criteria
minicluster,portablecluster) exist; discovery URLs resolve;groups_namescope granted to the clusters' groupskanidm-login.py --client minicluster --api-token <SA>yields a token carrying thegroups_nameclaimDepends on / linked
groups_nameclaim)Kanidm: provision a kubernetes OAuth2 client + machine SAs for cluster toolingto Kanidm: provision per-cluster OAuth2 clients + machine SAs for cluster tooling