# ============================================================================= # L0 STATIC — Keycloak client secrets are declared consistently, ordered by a REAL # Flux edge, and healed by a reconciler whose behaviour is proven offline # Catalog: docs/14 L0 row ("Pre-apply, in CI") — runs WITHOUT a cluster. # # R-IDP-03 (identity config is declarative) and R-IDP-04 (IdP secrets SOPS-encrypted) # are both implemented through ONE mechanism that FAILS OPEN: the KeycloakRealmImport # resolves each client's secret from a `(env:NAME)` placeholder mapped to a key of the # SOPS-encrypted keycloak-realm-clients Secret. When the operator cannot resolve a # placeholder it stores the LITERAL placeholder text as the client secret AND THE IMPORT # JOB STILL REPORTS SUCCESS — then rests at Done=True / Started=False and never re-runs. # # Measured 2026-09-06: prod had all 12 clients holding the literal placeholder (every # OIDC login failed with "Invalid client or Invalid client credentials"); dev had exactly # one (oauth2-proxy), because that Secret key was added AFTER dev's import completed. # Declarative config that silently does not apply is not declarative config. # # GIVEN the repository as authored, # THEN every confidential client declares a placeholder, every placeholder is defined, # resolves to the keycloak-realm-clients Secret, and names a key that EXISTS in the # SOPS file under the `-client-secret` contract the reconciler derives # from; public clients declare no secret; the Flux Kustomization applying the Secret # is a transitive `dependsOn` ancestor (wait: true) of the ones applying the import # and the reconciler — a real edge, not a comment; the reconciler is reconciled from # BOTH cluster entrypoints, mounts only what it needs, carries no ServiceAccount # token and contains no dollar sign; and its own `--selftest` (extracted from the # shipped ConfigMap and executed) proves compare-then-write, idempotence, # no-secret-logging, the endpoint allow-list and fail-closed behaviour. # # STATUS: EXECUTABLE. `check.sh` is a pure offline assertion script (git + PyYAML + # stdlib); conformance/run.sh --layer l0 and ci/l0.sh run it directly, and this Chainsaw # Test wraps the SAME script. # # NOT proven here: that the LIVE realm's stored secrets match git (that is # tests/l2-behavioral/keycloak-client-secrets-match-git), that the SOPS ciphertext # decrypts to a usable value (key PRESENCE is offline-checkable; plaintext is not), or # that the CronJob's schedule fires. # ============================================================================= apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Test metadata: name: keycloak-client-secret-reconciler labels: conformance.home.k3s/R-IDP-03: "true" conformance.home.k3s/R-IDP-04: "true" annotations: conformance.home.k3s/requirements: "R-IDP-03, R-IDP-04" conformance.home.k3s/layer: "L0" # WHOLE-REPO SCOPE — relocated verbatim from ci/l0.sh's hand-written "Stage 3d # (UNCONDITIONAL)", which this annotation replaces: # # The Keycloak realm import resolves each OIDC client's secret from an `(env:NAME)` # placeholder. When the operator cannot resolve one it stores the LITERAL placeholder as # the client secret AND THE IMPORT JOB STILL REPORTS SUCCESS, then rests at Done=True and # never re-runs. On 2026-09-06 that had all 12 prod clients unusable ("Invalid client or # Invalid client credentials") behind an entirely green cluster; dev had one. # # WHY IT MUST NOT BE REQUIREMENT-SCOPED: this check's invariant spans platform/, # platform-config/ and clusters/, so a change that breaks it need not attribute # R-IDP-03/04 and the requirement-scoped selection would filter it out of exactly the # change that introduces the bug. conformance.home.k3s/scope: "whole-repo" conformance.home.k3s/safety-critical: "false" conformance.home.k3s/executable: "true" conformance.home.k3s/intent: >- Every OIDC client's secret is declared once, resolvable, ordered behind a real Flux dependency, and continuously reconciled — so an unresolved import placeholder can neither be merged nor silently persist in the realm. spec: steps: - name: audit-declaration-ordering-and-reconciler description: >- Assert the realm import, the SOPS Secret and the reconciler agree; that the Flux ordering is a real dependsOn edge; and run the reconciler's own selftest. try: - script: content: bash ./check.sh