Files
home-network-k3s/docs/15-identity-and-access.md
T
jakman85andClaude Opus 4.8 fb153f0bb5 Add Keycloak IdP / SSO (ADR-0014, docs/15, R-IDP-*)
New identity subsystem, and resolves the C2 auth open question:
- docs/15-identity-and-access.md + ADR-0014: Keycloak as central IdP; native
  OIDC where supported (Gitea, Nextcloud, Grafana, Kasm, Semaphore, Headlamp)
  and oauth2-proxy forward-auth for bare UIs (PiHole, *arr, qBittorrent,
  Homepage, Prometheus, Alertmanager, Hubble). Group-based authz + MFA;
  declarative realm/clients (GitOps); PostgreSQL on Longhorn, DR-critical +
  break-glass; hardened public exposure. Plex/Seerr use Plex auth; Minecraft N/A.
- Requirements R-IDP-01..06; ServiceDefinition gains an  block.
- Onboarded early (with Gitea) so services adopt SSO as they come up.
- Threaded through: docs 00,01,07,10,12,13; roadmap phases+workstreams;
  task board (T-6.1c/T-6.1d); glossary; ADR index; README.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-08-15 23:33:49 -05:00

5.8 KiB

15 — Identity & Access (SSO)

Serves: R-IDP-01..06, supports R-C2-02, R-SEC-02/03. Related: ADR-0014 (Keycloak).

Purpose

One place to log in. A central Identity Provider (IdP) gives the platform single sign-on (SSO), one user directory, group-based authorization, and MFA — so every service is protected by the same identity, and no management UI sits unauthenticated on the network.

Choice: Keycloak

Keycloak is the platform IdP (ADR-0014): a mature, self-hostable OpenID Connect (OIDC) + SAML provider with users, groups, roles, clients, MFA (TOTP/WebAuthn), and brute-force protection.

Two integration patterns (behind one identity)

Every service authenticates against Keycloak, via whichever pattern it supports:

  1. Native OIDC — the app is configured as a Keycloak OIDC client and does its own login redirect. Preferred where available. Initial set: Gitea, Nextcloud, Grafana, Kasm, Semaphore, Headlamp.
  2. Forward-auth proxy — for apps with no usable OIDC, an identity-aware proxy (oauth2-proxy) sits in front at the Gateway, authenticates the user against Keycloak, and only then forwards the request. Used for: *PiHole admin, the arr web UIs (Sonarr/Radarr/Jackett), qBittorrent UI, Homepage, Prometheus, Alertmanager, Hubble UI, and any other bare UI.

This resolves the C2 auth open question (12): it is both — native OIDC where supported, forward-auth everywhere else, all backed by Keycloak.

Exceptions (documented, not oversights)

  • Plex and Seerr use Plex's own account system (Plex OAuth) — they do not federate to Keycloak.
  • Minecraft authenticates players via Mojang/Microsoft — N/A.
  • UniFi keeps its native account model (limited SSO support); protect its UI via forward-auth if desired.

Authorization model (R-IDP-06)

  • Groups drive access. Keycloak groups (e.g. platform-admins, media-users, viewers) map to per-service access and roles. A service's ServiceDefinition declares which groups may reach it (13, auth.groups).
  • Least privilege: the C2 console, Headlamp, Alertmanager, and other sensitive UIs require an authenticated user in an authorized group — not merely "logged in."
  • MFA: TOTP/WebAuthn available for all users and required for privileged groups (platform-admins).

Identity config as code (R-IDP-03)

Realms, clients, groups, and roles are declarative and GitOps-managed — not clicked into the admin console and forgotten:

  • The Keycloak instance is deployed via the Keycloak Operator (or Helm), and realm/client/group configuration is reconciled declaratively (e.g. keycloak-config-cli or realm-import CRs). Exact tool is an implementation detail; the requirement is that identity config lives in git and reconciles like everything else.
  • OIDC client secrets and the Keycloak admin credential are SOPS-encrypted (07).

State, exposure & resilience

  • Datastore: Keycloak runs on PostgreSQL; the DB lives on 3-replica Longhorn and is DR-critical → backed up off-cluster (04). Keycloak is stateless itself and rebuilds from the DB + git-managed realm config.
  • Exposure: keycloak.home.keithjackson.dev is public so it can serve login/redirect flows for the internet-exposed services (Nextcloud, Gitea) — but it is security-sensitive and hardened: brute-force detection on, strong admin auth + MFA, trusted TLS (08), minimal exposed endpoints. If the operator prefers internal-only, public services fall back to their native auth.
  • HA: a single replica with DB on Longhorn + backups is acceptable for the home scale; note clustered Keycloak as a future hardening. Availability caveat: SSO becomes a dependency for logging into federated services — document a break-glass path (e.g. a local admin on Gitea) so an IdP outage doesn't lock the operator out of recovery tools.

Interaction with default-deny & the gateway

  • Keycloak and oauth2-proxy are ordinary workloads under default-deny (03); the specific flows they need (app → Keycloak OIDC, proxy → Keycloak, Keycloak → its DB) are explicit allow rules.
  • Forward-auth is enforced at the Gateway (09) so protection happens before traffic reaches the app.

Bootstrapping & order

  • Keycloak is foundational and onboarded early (with PiHole/Gitea, 13) so later services can integrate SSO as they come up.
  • No hard circular dependency at bring-up: Gitea can start with a local admin and add OIDC once Keycloak is live; the C2 and sensitive UIs gain SSO as soon as the proxy + realm exist.

Acceptance gates

  • A user logs in once at Keycloak and reaches all OIDC-integrated services without re-entering credentials (SSO proven).
  • A forward-auth-protected UI (e.g. PiHole admin) is unreachable without a valid Keycloak session and reachable with one, restricted to the allowed group.
  • Realm/client/group config applied purely from git reproduces a working SSO setup (no console clicking); destroying and rebuilding Keycloak from DB + git restores identity.
  • Privileged access (C2/Headlamp) requires MFA and group membership; a non-member is denied.
  • Client secrets and admin credentials exist only SOPS-encrypted.

Open questions

  • Final declarative-config tool (keycloak-config-cli vs operator realm-import CRs) — implementation detail for WS-SEC.
  • Confirm public exposure for Keycloak (recommended) vs internal-only with native-auth fallback for public services.