Commit Graph

26 Commits

Author SHA1 Message Date
unkin-agent 3396b399ce Jellyfin SSO: cheeztv OIDC hosts, media-group gating, LDAP outpost
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline failed
Completes the Authentik-side plumbing for Jellyfin SSO across both media
instances -- fafflix (adults, jellyfin.k8s.syd1.au.unkin.net) and cheeztv
(kids, cheeztv.unkin.net + cheeztv.k8s.syd1.au.unkin.net) -- and adds an
LDAP outpost so native clients can authenticate with app passwords.

Why: the previously-merged jellyfin OIDC provider only covered the fafflix
host and gated on the generic jellyfin permission groups. cheeztv needs SSO
too, access should be limited to media users, and native (non-browser)
clients need a password-based path.

How:
- providers_oauth2/jellyfin.yaml: one shared confidential client now lists
  strict redirect URIs for all three hosts using the verified
  jellyfin-plugin-sso callback path /sso/OID/redirect/authentik. Client
  secret moved to kv kubernetes/namespace/fafflix/default/oauth-credentials.
- Access is gated to media users only: akP-media-fafflix and akP-media-cheeztv
  now carry `application: jellyfin` and bind to the app; akP-jellyfin-admin /
  akP-jellyfin-user are demoted to pure role-claim groups (no app binding),
  still mapped by the plugin for admin/user rights. Per-instance authz
  (adults -> both, kids -> cheeztv only) stays with the media proxy.
- providers_ldap/jellyfin-ldap.yaml: new LDAP provider (base_dn
  DC=ldap,DC=goauthentik,DC=io, direct bind/search) + application
  (jellyfin-ldap) + outpost (jellyfin-ldap-outpost) via the existing module.
- modules/authentik/main.tf: resolve LDAP bind/unbind flow slugs to ids via
  data.authentik_flow, matching the oauth2/saml convention.
2026-08-26 22:15:28 +10:00
unkin-agent 643c484dea watchstate: add external watchstate.unkin.net redirect URI
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
watchstate is being exposed externally at watchstate.unkin.net; oauth2-proxy needs the external callback registered.
2026-08-25 21:42:26 +10:00
unkin-agent db5bf753b5 Onboard watchstate into Authentik for oauth2-proxy
ci/woodpecker/pr/plan Pipeline failed
ci/woodpecker/pr/pre-commit Pipeline was successful
watchstate is an internal media watch-state sync admin tool deployed at
watchstate.k8s.syd1.au.unkin.net behind oauth2-proxy (OIDC against
Authentik). Add the OAuth2/OIDC provider + application mirroring the
logviewer/traefik in-cluster admin pattern, gate it with the
akP-watchstate-admin permission group bound to the app, and nest that
permission into the akR-global-admin role so only the admin team can
authorize.
2026-08-25 20:11:38 +10:00
unkin-agent ec0646657d Add adult/kids media groups for media split
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
The media services are splitting into an adult (fafflix) and kids (cheeztv)
tier, and Authentik group membership will drive the media proxy's routing and
authorization. This adds the two-tier RBAC groups so users can be assigned the
right media access ahead of the provider/application wiring.

- Add akP-media-fafflix and akP-media-cheeztv per-service permission entitlements
  (unbound, so they surface in the hierarchical ak_groups claim for the proxy)
- Add akR-media-adult role nesting both fafflix and cheeztv (adults reach both)
- Add akR-media-kids role nesting only cheeztv (kids reach kids services only)
2026-08-24 22:01:25 +10:00
unkin-agent 0480303db6 Merge origin/main (traefik #20) into benvin/logviewer-oidc
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
2026-08-23 22:48:36 +10:00
unkin-agent 937efb0360 Merge origin/main (jellyfin #19) into benvin/logviewer-oidc
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
Resolve akR-global-admin.yaml keeping both akP-jellyfin-admin (main) and
akP-logviewer-admin (this branch).
2026-08-23 22:41:11 +10:00
unkin-agent c1eea2d441 Merge remote-tracking branch 'origin/main' into benvin/traefik-oidc
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
# Conflicts:
#	config/roles/akR-global-admin.yaml
2026-08-23 22:14:06 +10:00
unkin-agent 43d325146c Add logviewer OAuth2 provider/application and akP-logviewer-admin permission
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
The ClickHouse log UI (logviewer) is being exposed at
https://logviewer.unkin.net behind oauth2-proxy in the logging namespace;
this adds the Authentik side as the prerequisite.

- Adds config/providers_oauth2/logviewer.yaml mirroring traefik: confidential
  client, client_id logviewer, secret from Vault kv
  kubernetes/namespace/logging/default/oauth-credentials,
  openid/email/profile scopes (ak_groups is attached to every oauth2
  provider by the module), strict redirect URI for the
  logviewer oauth2 callback.
- Adds config/permissions/akP-logviewer-admin.yaml bound to the logviewer
  application and nests it under akR-global-admin.
2026-08-23 17:24:18 +10:00
unkin-agent 1872b82550 Add traefik OAuth2 provider/application and akP-traefik-admin permission
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
The traefik dashboards (internal + external ingress classes) are being
exposed behind oauth2-proxy; this adds the Authentik side as the
prerequisite.

- Adds config/providers_oauth2/traefik.yaml mirroring arrstack: confidential
  client, client_id traefik, secret from Vault kv
  kubernetes/namespace/traefik-system/default/oauth-credentials,
  openid/email/profile scopes (ak_groups is attached to every oauth2
  provider by the module), strict redirect URIs for
  traefik-internal/traefik-external oauth2 callbacks.
- Adds config/permissions/akP-traefik-admin.yaml bound to the traefik
  application and nests it under akR-global-admin.
2026-08-23 12:35:17 +10:00
unkin-agent bbbb61777c Add Jellyfin OIDC provider, application and RBAC groups
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
Jellyfin moves to Authentik SSO via jellyfin-plugin-sso (OIDC), keeping
native clients on Jellyfin local/API auth. Adds the oauth2 provider and
application for jellyfin.k8s.syd1.au.unkin.net plus the akP permission
groups gating access, wired into the standard-user and global-admin
roles per the two-tier RBAC model.

- Adds providers_oauth2/jellyfin.yaml: confidential client, secret read
  from kv/kubernetes/namespace/jellyfin/default/oauth-credentials,
  redirect URIs for the SSO plugin callback paths
- Adds akP-jellyfin-admin and akP-jellyfin-user bound to the app
- Nests akP-jellyfin-user under akR-standard-user and
  akP-jellyfin-admin under akR-global-admin
2026-08-23 12:33:55 +10:00
unkin-agent e7c1f561f1 add arrstack oauth app + per-app access groups
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline failed
Add the Authentik OIDC application that fronts the arrproxy media front door
at arrstack.unkin.net, plus the per-app entitlement groups arrproxy reads from
the user's groups claim to decide which backends (sonarr/radarr/prowlarr) a
user may reach.

- config/providers_oauth2/arrstack.yaml: confidential oauth2 client
  client_id=arrstack, litellm-style auth/invalidation flows, client_secret
  from Vault kv kubernetes/namespace/arrstack/default/oauth-credentials,
  openid/email/profile scopes, redirect https://arrstack.unkin.net/oauth2/callback,
  launch https://arrstack.unkin.net/. The module always attaches the estate's
  hierarchical ak_groups scope mapping, so the front door emits the groups claim.
- config/permissions/akP-arrstack-user.yaml: front-door gate (application: arrstack).
- config/permissions/akP-arrstack-{sonarr,radarr,prowlarr}.yaml: per-app
  entitlements, unbound (no application) so they only surface in the ak_groups
  claim for arrproxy to authorize backends.
- config/roles/akR-arrstack-user.yaml: full media role nesting all four.
- akR-global-admin: also nests the arrstack front door + all per-app perms.
2026-08-16 15:00:05 +10:00
unkinben a93205bc82 Set explicit launch URL for the LiteLLM application
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
Ben (akR-global-admin) does not see the LiteLLM tile on the Authentik user
dashboard, while ArgoCD/Grafana/Rancher appear normally. The live API shows
LiteLLM is configured identically to those apps: the app exists, its access
binding akP-litellm-admin -> litellm is present, and akR-global-admin nests
akP-litellm-admin (bidirectionally, same as the others). A CI-style plan against
live state reports "No changes" -- so this is not terraform-correctable drift,
and a plain re-apply fixes nothing. Yet check_access for Ben returns
passing=false for litellm and passing=true for the rest: a stale cached access
policy result inside Authentik.

Add an optional per-app launch_url to the providers_oauth2 config (default null,
which keeps Authentik's redirect-derived URL) and wire it to the application's
meta_launch_url. Set it for LiteLLM to its UI. This makes the dashboard tile
deterministic and, on apply, re-saves the application -- invalidating the stale
access-policy cache so Ben's (already-correct) access re-evaluates and the tile
appears.

Claude-Session: https://claude.ai/code/session_015ur3i7D2azsMAWTSVABApv
2026-07-31 20:46:35 +10:00
unkinben 1922014ab9 Update Gitea OIDC redirect URIs to canonical + admin route
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
The k8s Gitea drops SSH and serves git.unkin.net (canonical) plus
git.k8s.syd1.au.unkin.net (admin/backup route, live now via external-dns).
Replace the old git2 validation host in the OAuth2 redirect URIs to match
argocd-apps#309.

Claude-Session: https://claude.ai/code/session_015ur3i7D2azsMAWTSVABApv
2026-07-31 00:02:48 +10:00
unkinben 0ba2785eb5 Add Gitea OAuth2/OIDC provider + application
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
Register the k8s Gitea forge as an Authentik OIDC app so it can use SSO at
cutover. Redirect URIs cover both the temporary git2 validation host and the
final git.unkin.net host so login works across the migration.

- add config/providers_oauth2/gitea.yaml (confidential OAuth2 provider + app,
  client_secret read from kv/kubernetes/namespace/gitea/default/oauth-credentials)

Claude-Session: https://claude.ai/code/session_015ur3i7D2azsMAWTSVABApv
2026-07-29 22:01:58 +10:00
unkinben 8fa4192cc6 Add NetBox OAuth2/OIDC provider + application
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline failed
NetBox is being deployed to k8s (argocd-apps) with Authentik SSO via
python-social-auth's OpenIdConnectAuth backend. Add the confidential OAuth2
provider/application (client_id netbox, openid/email/profile scopes, strict
redirect to /oauth/complete/oidc/); the client_secret is read from Vault at
kubernetes/namespace/netbox/default/oauth-credentials (the terraform-authentik
runner policy already covers namespace/+/default/oauth-credentials).

Claude-Session: https://claude.ai/code/session_015ur3i7D2azsMAWTSVABApv
2026-07-28 16:44:52 +10:00
benvin bd2ead5855 Merge branch 'main' into benvin/ceph-saml
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
2026-07-24 22:16:29 +10:00
unkinben 7610627168 Add LiteLLM RBAC: akP-litellm groups + role claim mapping
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
Bring LiteLLM into the two-tier RBAC and map groups to LiteLLM roles.

- akP-litellm-admin / akP-litellm-user permission groups (bound to the litellm
  app for access); added to akR-global-admin / akR-standard-user roles.
- Generic per-provider role_mappings: emit an app role claim computed from
  effective (hierarchical) group membership. LiteLLM: emits `litellm_role`
  (proxy_admin for akP-litellm-admin, internal_user for akP-litellm-user, else
  internal_user_view_only); LiteLLM reads it via GENERIC_USER_ROLE_ATTRIBUTE.

Validated: plan 5 to add, 3 to change; generated role expression renders correctly.
2026-07-19 18:42:36 +10:00
unkinben 9c5937776e Add Ceph dashboard SAML provider
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline failed
Ceph dashboard SSO is SAML 2.0 (no native OIDC), so onboard it via an Authentik
SAML provider + application. Also resolve SAML authorization/invalidation flows
by slug and the signing keypair by name (mirrors the oauth2 handling), since the
SAML path had not been exercised before.

- config/providers_saml/ceph.yaml: SP entity id/ACS derived from the dashboard
  base URL (audience .../auth/saml2/metadata, acs .../auth/saml2, HTTP-POST),
  signed with the built-in self-signed keypair.

Ceph side (separate, Puppet): ceph dashboard sso setup saml2
  https://dashboard.ceph.unkin.net <authentik-idp-metadata-url>

Validated with `terragrunt plan`: 2 to add (provider + application).
2026-07-19 02:22:23 +10:00
unkinben 9098c7dcfc Add LiteLLM OAuth2/OIDC provider
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
SSO for LiteLLM (litellm.k8s.syd1.au.unkin.net) via Authentik generic OIDC.
Confidential OAuth2 provider + application, openid/email/profile scopes,
/sso/callback redirect. client_secret read from Vault at
kv/kubernetes/namespace/litellm/default/oauth-credentials (seeded).
2026-07-19 02:19:19 +10:00
unkinben 805ea48a36 Derive group name from filename; use distinct ak_groups claim
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
- Permission/role group name now comes from the config filename (the map key),
  dropping the redundant `name` field from each YAML and the object types.
- The hierarchical mapping emits an `ak_groups` claim (scope `ak_groups`) instead
  of `groups`, so it never collides with the direct-groups the default profile
  mapping already emits under `groups` (Authentik overrides same-key claims in an
  unpredictable order). Apps request the `ak_groups` scope and read that claim.
2026-07-18 16:19:34 +10:00
unkinben 1dab2ecc6f Add two-tier RBAC: permission/role groups, access policies, group claim
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
Introduce a user -> role -> [permissions] model for app access and roles,
managed declaratively.

- Permission groups (akP-<app>-<access>) under config/permissions/: atomic units,
  each names the application it grants access to.
- Role groups (akR-<role>) under config/roles/: what users are assigned to;
  each nests permission groups via parents (akR-global-admin -> all *-admin,
  akR-standard-user -> all *-user). Split into a separate authentik_group
  resource so roles can reference permission ids without self-reference.
- Policy bindings gate each application to its permission groups (and, via
  child->parent membership propagation, the roles that nest them).
- Hierarchical `groups` scope mapping: walks user groups up through .parents so
  the OIDC claim includes inherited permission groups (works around
  goauthentik/authentik#15579). Inert until a provider requests the `groups`
  scope, so no behaviour change to existing apps until they opt in.

Validated with `tofu validate`.
2026-07-18 16:11:39 +10:00
unkinben 58e17d5ae8 Add Rancher OAuth2/OIDC provider
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
Extends Authentik SSO to Rancher (rancher.k8s.syd1.au.unkin.net) so cluster
access uses Authentik identity and groups.

- Add config/providers_oauth2/rancher.yaml: confidential OAuth2 provider +
  application (slug rancher), openid/email/profile scopes, /verify-auth
  redirect (Rancher's OIDC callback). client_secret read from Vault at
  kv/kubernetes/namespace/cattle-system/default/oauth-credentials.
2026-07-15 20:59:38 +10:00
unkinben c62fdb574a Add argocd-admins group
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
Declaratively manage the group that argocd-rbac-cm maps to role:admin, so
onboarding ArgoCD SSO does not require creating the group by hand in the UI.
2026-07-12 22:58:32 +10:00
unkinben 1fc0b70e1a Add ArgoCD OAuth2/OIDC provider
Extends Authentik SSO to ArgoCD so cluster operators log in with their
Authentik identity and group membership instead of the local admin account.

- Add config/providers_oauth2/argocd.yaml: confidential OAuth2 provider +
  application (slug argocd), client_id argocd, openid/email/profile scopes,
  web SSO and CLI (localhost:8085) redirect URIs. client_secret is read from
  Vault at kv/kubernetes/namespace/argocd/default/oauth-credentials, matching
  the existing Grafana pattern.
2026-07-12 22:58:32 +10:00
unkinben 97be93a9ff authentik: add Grafana OAuth2/OIDC provider + application
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline failed
Adds an OIDC provider + application so the in-cluster Grafana
(grafana.k8s.syd1.au.unkin.net) can authenticate users against Authentik.

Extends the oauth2 module so provider config stays declarative and
secret-free:
- Resolve authorization/invalidation flows by slug (data.authentik_flow)
  and scope mappings by managed identifier
  (data.authentik_property_mapping_provider_scope).
- Read client_secret from Vault kv-v2 (data.vault_kv_secret_v2) instead of
  committing it; adds the hashicorp/vault provider (auth via VAULT_ADDR/
  VAULT_TOKEN from the Makefile).
- Support allowed_redirect_uris on the oauth2 provider.

config/providers_oauth2/grafana.yaml wires client_id `grafana`, the
openid/email/profile scopes, the login/generic_oauth redirect URI, and
points client_secret at kv/kubernetes/namespace/grafana/default/oauth-credentials.
2026-07-06 22:06:48 +10:00
unkinben 4042760a16 Initial scaffold
ci/woodpecker/pr/plan Pipeline failed
ci/woodpecker/pr/pre-commit Pipeline failed
- Terraform module for groups, SAML/OAuth2/LDAP providers, applications, and LDAP outposts
- Data-driven YAML config with Terragrunt config loader
- Environment: identity.unkin.net with Consul backend
- Provider: goauthentik/authentik 2026.5.0
- Woodpecker CI pipelines (pre-commit, plan, apply)
- Makefile with Vault AppRole and K8s auth support
2026-06-28 11:55:26 +10:00