# ============================================================================= # L2 BEHAVIORAL — native-OIDC SSO via the central IdP (R-IDP-01) [RUNNABLE] # Spec: docs/15 identity-and-access; ADR-0014. Impl: Grafana as a Keycloak OIDC client # (platform/monitoring/kube-prometheus-stack.yaml auth.generic_oauth) — the self-contained SSO proof. # # GIVEN Grafana is deployed and configured as an OIDC client of the Keycloak `homelab` realm, # WHEN an unauthenticated browser starts the OIDC login (GET /login/generic_oauth) # -> THEN Grafana redirects (302) to the CENTRAL IdP's authorize endpoint on # keycloak.home.keithjackson.dev/realms/homelab — proving SSO is driven by the one IdP # (R-IDP-01: central Identity Provider as the single user directory). # # Goes GREEN once the grafana-oidc client-secret hand-off is filled and Keycloak + Grafana are up. # chainsaw v0.2.12: Job + status assert; no test-level finally. # ============================================================================= apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Test metadata: name: oidc-sso-grafana labels: conformance.home.k3s/R-IDP-01: "true" annotations: conformance.home.k3s/requirements: "R-IDP-01" conformance.home.k3s/layer: "L2" conformance.home.k3s/safety-critical: "false" conformance.home.k3s/executable: "true" conformance.home.k3s/intent: >- Grafana's OIDC login redirects to the central Keycloak realm — SSO is driven by the one IdP. spec: timeouts: apply: 60s assert: 3m exec: 3m steps: - name: given-grafana-is-an-oidc-client try: - assert: resource: apiVersion: apps/v1 kind: Deployment metadata: name: kube-prometheus-stack-grafana namespace: monitoring status: availableReplicas: 1 - name: then-login-redirects-to-keycloak-realm try: - apply: resource: apiVersion: batch/v1 kind: Job metadata: name: grafana-oidc-probe spec: backoffLimit: 2 activeDeadlineSeconds: 150 template: spec: restartPolicy: Never containers: - name: probe image: busybox:1.36.1 command: - sh - -c - | set -u svc="http://kube-prometheus-stack-grafana.monitoring.svc.cluster.local" # busybox wget has no --max-redirect; -S dumps every response header # (incl. the initial 302 Location to the IdP) before following, so the # grep below still matches the Keycloak authorize URL. (Grafana verified # live: 302 -> keycloak.home.keithjackson.dev/realms/homelab/.../auth.) out="$(wget -S -O /dev/null "$svc/login/generic_oauth" 2>&1 || true)" echo "$out" if echo "$out" | grep -qi 'keycloak.home.keithjackson.dev/realms/homelab'; then echo GRAFANA_OIDC_REDIRECT_OK else echo "FAIL: Grafana did not redirect to the Keycloak homelab realm"; exit 1 fi - assert: resource: apiVersion: batch/v1 kind: Job metadata: name: grafana-oidc-probe status: succeeded: 1 finally: - script: content: 'echo "teardown: chainsaw deletes the per-test namespace (Job included)"'