71 lines
3.5 KiB
YAML
71 lines
3.5 KiB
YAML
# =============================================================================
|
|
# L2 BEHAVIORAL — identity config as code (R-IDP-03, R-IDP-04, R-IDP-06) [RUNNABLE]
|
|
# Spec: docs/15 identity-and-access; ADR-0014. Impl: platform/keycloak/keycloak-realm-import.yaml.
|
|
#
|
|
# GIVEN the `homelab` realm (groups platform-admins/media-users/viewers, OIDC clients, brute-force,
|
|
# and the conditional MFA browser flow) is declared as a KeycloakRealmImport in git,
|
|
# WHEN the Keycloak Operator reconciles it
|
|
# -> THEN the import reaches Done=True — realm/groups/clients/roles + the MFA flow are applied
|
|
# PURELY from git (R-IDP-03 config-as-code; R-IDP-04 MFA flow bound; R-IDP-06 groups/roles for
|
|
# least-privilege). No console clicking.
|
|
#
|
|
# Goes GREEN once Keycloak is up + the realm client-secret hand-off (keycloak-realm-clients) is filled
|
|
# so the placeholder resolves and the import completes. chainsaw v0.2.12: script + block contains check.
|
|
# =============================================================================
|
|
apiVersion: chainsaw.kyverno.io/v1alpha1
|
|
kind: Test
|
|
metadata:
|
|
name: keycloak-config-as-code
|
|
labels:
|
|
conformance.home.k3s/R-IDP-03: "true"
|
|
conformance.home.k3s/R-IDP-04: "true"
|
|
conformance.home.k3s/R-IDP-06: "true"
|
|
annotations:
|
|
conformance.home.k3s/requirements: "R-IDP-03, R-IDP-04, R-IDP-06"
|
|
conformance.home.k3s/layer: "L2"
|
|
conformance.home.k3s/safety-critical: "false"
|
|
conformance.home.k3s/executable: "true"
|
|
conformance.home.k3s/intent: >-
|
|
The homelab realm (groups, clients, MFA flow) reconciles to Done purely from the git-managed
|
|
KeycloakRealmImport — no manual console configuration.
|
|
spec:
|
|
timeouts:
|
|
exec: 5m
|
|
steps:
|
|
- name: realm-import-reconciles-from-git
|
|
try:
|
|
- script:
|
|
content: |
|
|
set -u
|
|
# Poll the KeycloakRealmImport until the operator reports Done=True.
|
|
for i in $(seq 1 30); do
|
|
st="$(kubectl -n keycloak get keycloakrealmimport homelab \
|
|
-o jsonpath='{.status.conditions[?(@.type=="Done")].status}' 2>/dev/null || true)"
|
|
echo "poll $i: Done=$st"
|
|
if [ "$st" = "True" ]; then
|
|
echo "REALM_IMPORT_DONE_OK"
|
|
break
|
|
fi
|
|
sleep 10
|
|
done
|
|
check:
|
|
(contains($stdout, 'REALM_IMPORT_DONE_OK')): true
|
|
- name: privileged-group-and-mfa-flow-present
|
|
try:
|
|
- script:
|
|
content: |
|
|
set -u
|
|
# The realm import declares the browser-mfa flow + platform-admins group. Confirm the
|
|
# realm CR / import spec carries them (declared-in-git evidence; the live realm state is
|
|
# exercised by the login flows).
|
|
flow="$(kubectl -n keycloak get keycloakrealmimport homelab \
|
|
-o jsonpath='{.spec.realm.browserFlow}' 2>/dev/null || true)"
|
|
grp="$(kubectl -n keycloak get keycloakrealmimport homelab \
|
|
-o jsonpath='{.spec.realm.groups[*].name}' 2>/dev/null || true)"
|
|
echo "browserFlow=$flow groups=$grp"
|
|
echo "$flow" | grep -q 'browser-mfa' || { echo "FAIL: MFA browser flow not bound"; exit 1; }
|
|
echo "$grp" | grep -q 'platform-admins' || { echo "FAIL: platform-admins group missing"; exit 1; }
|
|
echo "MFA_AND_GROUPS_OK"
|
|
check:
|
|
(contains($stdout, 'MFA_AND_GROUPS_OK')): true
|