Q3.2a / plan-lasuite-drive-oidc-robustness.md Part A. The old setup_custom_tests.sh did a post-deploy in-place `abra app deploy --force --chaos` of the heavy 12-service stack to apply the OIDC env — flaky (collabora WOPI-discovery race + gunicorn-perms; JOURNAL Step 0). Since the OIDC env only affects backend/app and keycloak is live-warm, provision the per-run realm BEFORE the single deploy and wire OIDC into the .env at install time (no reconverge). - runner/run_recipe_ci.py: new _provision_deps() helper (warm/cold split + SSO enrich + write $CCCI_DEPS_FILE), used by both paths. New per-recipe OIDC_AT_INSTALL meta flag (added to _load_meta whitelist). When set + deps live-warm: provision BEFORE deploy_app; the install tier's install_steps.sh wires OIDC into the single deploy; post-deploy step runs only the MinIO bucket one-shot — no re-provision, no redeploy. Legacy post-deploy path unchanged for all other dep recipes (gated on `not oidc_at_install`). - tests/lasuite-drive/install_steps.sh (NEW): install-time OIDC env + secret wiring; no-ops on empty deps file (recipe still boots, OIDC test skips → F2-11 RED). - tests/lasuite-drive/setup_custom_tests.sh: trimmed to MinIO-bucket-only (OIDC moved out). - tests/lasuite-drive/recipe_meta.py: OIDC_AT_INSTALL = True. - JOURNAL-2: Step-0 root-cause failure logs captured before the fix. NOT a claim — validating 3x green (incl. now-required upgrade tier) before claiming Q3.2. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
78 lines
4.8 KiB
Bash
Executable File
78 lines
4.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# lasuite-drive — INSTALL-TIME OIDC wiring hook (Phase 2 Q3.2a;
|
|
# plan-lasuite-drive-oidc-robustness.md Part A).
|
|
#
|
|
# Runs during the install tier AFTER `abra app new` + EXTRA_ENV + `abra app secret generate`, and
|
|
# BEFORE the single `abra app deploy` (runner/harness/lifecycle.py::_run_install_steps). By writing
|
|
# the OIDC env + the real client secret into the app's `.env` HERE, the recipe deploys ONCE with
|
|
# OIDC already wired — eliminating the flaky post-deploy in-place `--force --chaos` 12-service
|
|
# reconverge that the old setup_custom_tests.sh did (collabora WOPI-discovery race; see JOURNAL
|
|
# Step 0). The orchestrator provisions the per-run realm/client on the live-warm keycloak BEFORE
|
|
# this hook and writes $CCCI_DEPS_FILE (the recipe→creds dict).
|
|
#
|
|
# Env supplied by the harness:
|
|
# CCCI_APP_DOMAIN — the per-run lasuite-drive app domain
|
|
# CCCI_APP_ENV — path to the app's .env (the one `abra app deploy` reads)
|
|
# CCCI_RECIPE — "lasuite-drive"
|
|
# CCCI_DEPS_FILE — JSON {keycloak: {domain, realm, client_id, client_secret, ...}} (may be empty)
|
|
set -euo pipefail
|
|
|
|
: "${CCCI_APP_DOMAIN:?missing}"
|
|
ENV_PATH="${CCCI_APP_ENV:?missing}"
|
|
|
|
# No deps file / no keycloak entry → install-time provisioning failed or was skipped. NO-OP so the
|
|
# recipe still boots without OIDC; the @requires_deps OIDC custom test then SKIPs and F2-11 flips
|
|
# the run RED (deps declared but SSO unverified). Never wire a partial/broken OIDC config.
|
|
if [ -z "${CCCI_DEPS_FILE:-}" ] || [ ! -s "${CCCI_DEPS_FILE}" ]; then
|
|
echo " install_steps: no deps file — skipping OIDC wiring (recipe boots without OIDC)"
|
|
exit 0
|
|
fi
|
|
KC_DOMAIN=$(jq -r '.keycloak.domain // empty' "$CCCI_DEPS_FILE")
|
|
KC_REALM=$( jq -r '.keycloak.realm // empty' "$CCCI_DEPS_FILE")
|
|
KC_CLIENT=$(jq -r '.keycloak.client_id // empty' "$CCCI_DEPS_FILE")
|
|
KC_SECRET=$(jq -r '.keycloak.client_secret // empty' "$CCCI_DEPS_FILE")
|
|
if [ -z "$KC_DOMAIN" ] || [ -z "$KC_SECRET" ]; then
|
|
echo " install_steps: deps file has no keycloak domain/secret — skipping OIDC wiring"
|
|
exit 0
|
|
fi
|
|
|
|
echo " lasuite-drive install_steps: wiring OIDC at install against keycloak ${KC_DOMAIN}"
|
|
|
|
# 1) Insert the OIDC client secret at a bumped version. `abra app secret generate` already created a
|
|
# random oidc_rpcs:v1; swarm forbids overwriting a secret at the same version, so insert v2 and
|
|
# point SECRET_OIDC_RPCS_VERSION at it. (The app is not deployed yet — a swarm secret can be created
|
|
# independently of a running stack — so the single deploy below picks up v2.)
|
|
CUR_VER=$(grep -E '^\s*SECRET_OIDC_RPCS_VERSION=' "$ENV_PATH" | tail -1 | cut -d= -f2 | tr -d '"\r' || echo "v1")
|
|
NEW_NUM=$(( ${CUR_VER#v} + 1 ))
|
|
NEW_VER="v${NEW_NUM}"
|
|
INSERT_LOG=$(abra app secret insert "$CCCI_APP_DOMAIN" oidc_rpcs "$NEW_VER" "$KC_SECRET" --no-input 2>&1) \
|
|
|| INSERT_LOG=$(script -qec "abra app secret insert $CCCI_APP_DOMAIN oidc_rpcs $NEW_VER $KC_SECRET --no-input" /dev/null 2>&1) \
|
|
|| { echo " install_steps: abra app secret insert oidc_rpcs@$NEW_VER failed: $INSERT_LOG"; exit 1; }
|
|
sed -i "s|^\s*SECRET_OIDC_RPCS_VERSION=.*|SECRET_OIDC_RPCS_VERSION=$NEW_VER|" "$ENV_PATH"
|
|
echo " install_steps: oidc_rpcs secret inserted at $NEW_VER (was $CUR_VER)"
|
|
|
|
# 2) Write the OIDC env vars (explicit endpoints — deterministic, no reliance on ${AUTH_DOMAIN}
|
|
# expansion). Mirrors the recipe-maintainer impress/La Suite OIDC env contract.
|
|
write_env () {
|
|
local key="$1" val="$2"
|
|
sed -i "/^\s*#\?\s*${key}=/d" "$ENV_PATH"
|
|
[ -z "$(tail -c1 "$ENV_PATH" 2>/dev/null)" ] || printf '\n' >> "$ENV_PATH"
|
|
printf '%s=%s\n' "$key" "$val" >> "$ENV_PATH"
|
|
}
|
|
write_env AUTH_DOMAIN "$KC_DOMAIN"
|
|
write_env OIDC_REALM "$KC_REALM"
|
|
write_env OIDC_OP_JWKS_ENDPOINT "https://${KC_DOMAIN}/realms/${KC_REALM}/protocol/openid-connect/certs"
|
|
write_env OIDC_OP_AUTHORIZATION_ENDPOINT "https://${KC_DOMAIN}/realms/${KC_REALM}/protocol/openid-connect/auth"
|
|
write_env OIDC_OP_TOKEN_ENDPOINT "https://${KC_DOMAIN}/realms/${KC_REALM}/protocol/openid-connect/token"
|
|
write_env OIDC_OP_USER_ENDPOINT "https://${KC_DOMAIN}/realms/${KC_REALM}/protocol/openid-connect/userinfo"
|
|
write_env OIDC_OP_LOGOUT_ENDPOINT "https://${KC_DOMAIN}/realms/${KC_REALM}/protocol/openid-connect/logout"
|
|
write_env OIDC_RP_CLIENT_ID "$KC_CLIENT"
|
|
write_env OIDC_RP_SIGN_ALGO "RS256"
|
|
write_env OIDC_RP_SCOPES "openid email profile"
|
|
write_env OIDC_REDIRECT_ALLOWED_HOSTS "[\"https://${KC_DOMAIN}\", \"https://${CCCI_APP_DOMAIN}\"]"
|
|
# The recipe default acr_values=eidas1 is FranceConnect-specific; keycloak can't satisfy it and it
|
|
# would break the interactive auth flow. Clear it so the keycloak OIDC client works.
|
|
write_env OIDC_AUTH_REQUEST_EXTRA_PARAMS "{}"
|
|
|
|
echo " lasuite-drive install_steps: OIDC env wired into .env (deploy will pick it up, no reconverge)"
|