Phase 28: Keycloak Declarative Onboarding

phase-platform-28-keycloak-declarative-onboarding Phase

active phase

Phase 28: Keycloak Declarative Onboarding

Goal: Manage Keycloak realms, clients, and roles declaratively in pal-e-services Terraform so that tofu apply creates full auth config alongside namespaces, Harbor projects, and ArgoCD apps — with disaster recovery from git.
Owner: Dev agent
Repo: forgejo_admin/pal-e-services
Depends on: Keycloak server deployed (pal-e-platform, done), admin password in pillar (PR #141, merged), theme files mounted (PR #130, merged)

Why

Today, onboarding auth for a new project requires 5+ manual steps in the Keycloak admin console — creating realms, clients, roles, redirect URIs, themes. These steps are untracked, unrepeatable, and unrecoverable. If the cluster is rebuilt from Terraform, all auth config is lost. 63 westside-basketball users, 3 mcd-tracker users — their realms, clients, and roles exist only in Keycloak's H2 database on a 2Gi PVC.

Scope

  • Add mrparkers/keycloak Terraform provider (~v5.x) to pal-e-services
  • New var.keycloak_realms top-level variable — project-level auth boundaries (decoupled from var.services because multiple services share one realm)
  • New var.keycloak_clients top-level variable — per-app OIDC client configs (decoupled from var.services because some clients have no corresponding deployed service, e.g. mcd-tracker-ios)
  • Import existing state: 2 realms (westside-basketball, mcd-tracker), 4 clients, 5 custom roles, 1 protocol mapper
  • Master realm explicitly excluded (admin realm, risk of lockout, static config)
  • Zero-diff plan gate — no apply until tofu plan shows zero changes
  • lifecycle { ignore_changes } on client secrets and default client scopes for import safety
  • Update service onboarding SOP

Deliverables

  • Ticket 1 (5 pts): Add Keycloak provider + import existing state. Zero-diff plan verified. PR merged.
  • Ticket 2 (1 pt): Update service onboarding SOP with keycloak_realms/keycloak_clients documentation.

Acceptance Criteria

  • tofu plan on existing state shows zero changes (import complete)
  • All 63 westside-basketball users can still log in after apply
  • Adding a new realm+client to tfvars and applying creates working auth
  • Service onboarding SOP updated — auth is part of onboarding
  • No manual Keycloak admin console actions required for new projects

Risk Surface

Risk Severity Mitigation
Client secrets regenerated on apply Critical <code>lifecycle { ignore_changes = [client_secret] }</code>
Protocol mapper deleted if undeclared Critical Explicit <code>keycloak_openid_user_realm_role_protocol_mapper</code> resource
Custom roles deleted if undeclared Critical Declare all roles in <code>var.keycloak_realms.roles</code>
registrationEmailAsUsername reset Critical Per-realm field, no shared default
Client scopes reset to provider defaults Medium <code>lifecycle { ignore_changes }</code> on realm
Keycloak down blocks all pal-e-services plans Medium Same two-phase pattern as ArgoCD provider

Testing Strategy

  • Import gate: tofu plan shows zero changes = import succeeded
  • Login smoke: 63 westside users can still log in
  • Drift detection: Change setting in admin console → tofu plan detects it
  • New project: Add test realm+client → tofu apply → login works
  • Rollback: Remove test realm → tofu apply → realm gone
  • plan-pal-e-platform — parent plan
  • Issue #142 — parent Forgejo issue
  • PR #130 — Keycloak theme (triggered this discovery)
  • PR #141 — Pillar secrets (Keycloak admin password now in pillar)
  • Spec: pal-e-platform/docs/superpowers/specs/2026-03-21-keycloak-terraform-onboarding-design.md