- tests/keycloak/PARITY.md: parity table (health_check ported); oidc_integration.py noted as Q3-deferred (cross-recipe test needs lasuite-docs + dep resolver). - tests/keycloak/functional/test_health_check.py: parity port of recipe-info/keycloak/tests/health_check.py — SOURCE comment. - tests/keycloak/functional/test_password_grant_token.py: NEW recipe-specific — password grant against /realms/master/protocol/openid-connect/token; decodes the JWT payload; asserts iss=https://<live_app>/realms/master, azp=admin-cli, typ=Bearer, exp in future, iat reasonable past. Reuses kc_admin.py helpers. - tests/keycloak/functional/test_create_client_and_use.py: NEW recipe-specific — admin creates a UUID-named confidential client via admin API → uses client credentials grant to obtain a service-account token → decodes JWT, asserts azp matches the new clientId, iss matches per-run domain → idempotent DELETE cleanup. - tests/keycloak/recipe_meta.py: bumped DEPLOY_TIMEOUT + HTTP_TIMEOUT 600 -> 900 (cold-start JVM + mariadb migration intermittently exceeds 600s on a 2-vCPU host; observed 502 fallback after 600s in run #1). Cold-verifiable on cc-ci (log /root/ccci-q2-keycloak-r3.log): RECIPE=keycloak cc-ci-run runner/run_recipe_ci.py all 5 stages PASS, deploy-count=1, head_ref=666649a6==chaos-version=666649a6 (HC1 non-vacuous), version 10.7.0+26.6.1 -> 10.7.1+26.6.2. Custom tier 3 PASS: parity health_check, JWT password-grant, client_credentials. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
41 lines
3.7 KiB
Markdown
41 lines
3.7 KiB
Markdown
# Parity — keycloak
|
|
|
|
Phase-2 P2 mapping table. The Adversary cold-verifies parity by reading the source
|
|
`recipe-info/keycloak/tests/<file>` and the cc-ci file side-by-side.
|
|
|
|
| recipe-maintainer file | cc-ci file | what's verified | status |
|
|
|---|---|---|---|
|
|
| `recipe-info/keycloak/tests/health_check.py` | `tests/keycloak/functional/test_health_check.py` | The keycloak master realm endpoint (`/realms/master`) returns HTTP 200 — the original's assertion shape, preserved. The cc-ci port adapts to the ephemeral per-run domain via the `live_app` fixture. | **ported** |
|
|
| `recipe-info/keycloak/tests/oidc_integration.py` | (deferred to Q3 lasuite-docs) | The original is a **cross-recipe** integration test: it expects both keycloak AND lasuite-docs deployed, with a pre-seeded credentials TOML, and proves a keycloak-issued token is accepted by lasuite-docs. This requires the Phase-2 dependency resolver (Q0.4/Q2.3) + lasuite-docs Phase-2 enrollment. Will land as `tests/lasuite-docs/functional/test_oidc_with_keycloak.py` in Q3, sharing the SSO-setup harness. | **deferred to Q3** (logged in DECISIONS.md) |
|
|
|
|
## Recipe-specific tests (Phase-2 P3, ≥2 beyond parity)
|
|
|
|
keycloak's characteristic behavior is **realm/client management + OIDC token issuance**. The
|
|
lifecycle overlays already prove the admin API works (`kc_admin.py` creates/queries/deletes a
|
|
marker realm across upgrade/backup/restore — Phase 1d/1e). Two new functional tests beyond parity:
|
|
|
|
| cc-ci file | what's verified | rationale |
|
|
|---|---|---|
|
|
| `tests/keycloak/functional/test_password_grant_token.py` | Obtains an admin-CLI access token via the password grant (`grant_type=password`) against `/realms/master/protocol/openid-connect/token`, asserts the token is a valid JWT (3 base64url-encoded segments), decodes the payload, and asserts the JWT claims include `iss` matching the live domain, `azp == "admin-cli"`, `typ == "Bearer"`, and a future `exp`. | The defining keycloak behavior is issuing JWTs; this test does the canonical password-grant flow against the real running keycloak (real admin user, real password from the abra-generated secret) and proves the JWT contract is intact. Non-vacuous: a wrongly-configured realm, broken signing key, or wrong issuer would fail the claim assertions. |
|
|
| `tests/keycloak/functional/test_create_client_and_use.py` | Authenticates as admin → creates a confidential client in the master realm via admin API with a known `clientId` + a known client secret → obtains a token via `grant_type=client_credentials` for that client → asserts the token's `azp` (authorized party) matches the new client's clientId → deletes the client (idempotent cleanup). | Proves the full lifecycle of admin-API client creation + service-account token issuance, the canonical "real app integrating with keycloak" flow. Non-vacuous: tests TWO grant types (password + client-credentials) and the admin-API CRUD on clients. |
|
|
|
|
Both tests run in the **custom** tier against the same `live_app` shared deployment as the
|
|
lifecycle overlays — no extra deploy, no extra teardown.
|
|
|
|
## Backup data-integrity (P4)
|
|
|
|
Already exercised by the lifecycle overlays: `kc_admin.create_marker_realm` (mariadb data) before
|
|
backup, mutated by deletion before restore, asserted present after restore. See
|
|
`tests/keycloak/{ops.py,test_upgrade.py,test_backup.py,test_restore.py}` + `kc_admin.py`.
|
|
|
|
## Playwright (P6)
|
|
|
|
The keycloak admin console (login form) is loaded by `tests/keycloak/test_install.py::
|
|
test_serving_and_admin_console` (lifecycle install overlay). Adequate for P6 — the admin UI is the
|
|
recipe's primary browser surface.
|
|
|
|
## Non-ports
|
|
|
|
`oidc_integration.py` is deferred to Q3 (cross-recipe test; needs lasuite-docs Phase-2 enrollment +
|
|
the dependency-resolver harness primitive). Logged in DECISIONS.md Phase-2 section.
|