Commit Graph

14 Commits

Author SHA1 Message Date
benvin 132da3cfc8 Merge pull request 'Set explicit launch URL for the LiteLLM application' (#16) from benvin/litellm-app-visibility into main
ci/woodpecker/push/apply Pipeline was successful
Reviewed-on: #16
2026-07-31 22:00:02 +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 b6e9b6b6b9 Default OAuth2 providers to RS256 ID token signing
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
OAuth2 providers with no signing_key fall back to HS256, which RS256-only
RP clients (argocd confirmed, and the rest) reject with "unexpected
signature algorithm HS256; expected [RS256]", breaking OIDC login.

- Add data.authentik_certificate_key_pair.signing, resolving the estate's
  RSA keypair by name (var.oauth2_signing_key_name, default the built-in
  "authentik Self-signed Certificate").
- Default every provider's signing_key to that keypair via coalesce, so all
  providers sign with RS256 while keeping the per-yaml signing_key override.

Claude-Session: https://claude.ai/code/session_015ur3i7D2azsMAWTSVABApv
2026-07-31 20:28:07 +10:00
unkinben 2b39450ae2 Set OAuth2 grant_types so authorization_code login works
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
## Why

All Authentik OIDC logins (ArgoCD, Grafana, Rancher, LiteLLM, NetBox) fail
with `invalid_request` / "The request is otherwise malformed". Authentik
2026.5 added an explicit `grant_types` allow-list to the OAuth2 provider
(model default = empty list). Our module never set it, so every provider has
`grant_types = []`, and `authorize.py` rejects the authorization_code grant
(`if self.grant_type not in self.provider.grant_types`) before any user auth.

## Change

- modules/authentik: add a `grant_types` field to the `providers_oauth2`
  variable, defaulting to `["authorization_code", "refresh_token"]` (the
  standard confidential web-app set), and wire it into
  `authentik_provider_oauth2`.

## Plan

`0 to add, 5 to change, 0 to destroy` — each existing oauth2 provider's
`grant_types` goes `[] -> ["authorization_code", "refresh_token"]`; no other
attributes change. Baseline plan (pre-change) was clean (no netbox/state drift).

Claude-Session: https://claude.ai/code/session_015ur3i7D2azsMAWTSVABApv
2026-07-28 22:09:06 +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 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 5faa2f84f6 Fix perpetual redirect_uri drift on oauth2 providers
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
authentik_provider_oauth2.allowed_redirect_uris is list(map(string)) and the
API always stores a redirect_uri_type key on each entry. The module only set
matching_mode and url, so every plan showed the Grafana provider being updated
in-place (state map had 3 keys, config map had 2) and never converged.

Add redirect_uri_type to the redirect_uris object, defaulting to
"authorization". `terragrunt plan` now reports no changes.
2026-07-12 22:57:57 +10:00
unkinben 7636d45f21 Fix self-referential authentik_group parents
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
Adding the first managed group (argocd-admins) exposed a dormant bug: the
groups resource resolved `parents` by indexing authentik_group.this itself,
which OpenTofu rejects as a self-referential block. config/groups/ had been
empty, so `tofu plan` never hit it before.

Pass `parents` through as literal group PKs instead (the resource cannot
reference itself, so parent-by-map-key was never viable). Plan is clean:
3 to add (argocd provider, application, argocd-admins group).
2026-07-12 22:42:17 +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 8aa2273dcf Fix provider schema for goauthentik/authentik 2026.5.0
ci/woodpecker/pr/plan Pipeline failed
ci/woodpecker/pr/pre-commit Pipeline was successful
- group: parent → parents (list)
- saml/oauth2: add required invalidation_flow
- oauth2: remove redirect_uris (use allowed_redirect_uris via config)
- ldap: replace authorization_flow/search_group with bind_flow/unbind_flow
- Add versions.tf with required_providers block
- Remove service_connection from outpost (auto-discovered)
2026-06-28 12:04:19 +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