#!/usr/bin/env bash # test-scenario-b.sh — Scenario B: IAM swap (KeyCape -> Keycloak, same LLDAP directory). # # Exports the canonical directory, transforms it into a Keycloak realm, starts # Keycloak over that realm, and runs the external conformance suite against it. # # Prerequisites: docker, docker compose, and `make -C src build` (root `make build` only compiles; the src target installs into bin/). set -euo pipefail REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$REPO_ROOT" BUILD_DIR="$REPO_ROOT/build/scenario-b" COMPOSE="docker compose -f docker-compose.scenario-b.yml" ISSUER_URL="http://localhost:8080/realms/netkingdom" die() { echo "scenario-b: $*" >&2; exit 1; } # Check every prerequisite up front: failing half way through leaves a running # stack and a half-written realm, which is harder to diagnose than not starting. for binary in lldap-export keycape-to-keycloak; do [ -x "bin/$binary" ] || die "bin/$binary is missing; run 'make -C src build' first" done command -v docker >/dev/null || die "docker is not installed" command -v go >/dev/null || die "go is not installed" cleanup() { $COMPOSE down -v >/dev/null 2>&1 || true; } trap cleanup EXIT mkdir -p "$BUILD_DIR/realm" echo "=== Scenario B: IAM replacement ===" echo "--- Step 1: start the directory ---" $COMPOSE up -d lldap timeout 120 bash -c 'until (exec 3<>/dev/tcp/127.0.0.1/3890) 2>/dev/null; do sleep 2; done' \ || die "LLDAP did not accept connections within 120s" echo "--- Step 2: export the canonical directory ---" ./bin/lldap-export \ --url "${LLDAP_URL:-ldap://localhost:3890}" \ --bind-dn "${LLDAP_BIND_DN:-cn=admin,ou=people,dc=netkingdom,dc=local}" \ --bind-pw "${LLDAP_BIND_PW:-adminpassword}" \ --base-dn "${LLDAP_BASE_DN:-dc=netkingdom,dc=local}" \ --output "$BUILD_DIR/canonical-export.yaml" echo "--- Step 3: transform into a Keycloak realm ---" ./bin/keycape-to-keycloak \ --input "$BUILD_DIR/canonical-export.yaml" \ --realm netkingdom \ --issuer "${ISSUER:-$ISSUER_URL}" \ --output "$BUILD_DIR/realm/netkingdom-realm.json" echo "--- Step 4: start Keycloak over the migrated realm ---" $COMPOSE up -d keycloak timeout 180 bash -c "until curl -sf '$ISSUER_URL/.well-known/openid-configuration' >/dev/null; do sleep 3; done" \ || die "Keycloak did not serve discovery within 180s" echo "--- Step 5: run the external conformance suite against Keycloak ---" # The suite reads KEYCAPE_TEST_ISSUER and talks to the running issuer over HTTP. # Run it from the module directory: the Go module root is src/, not the repo root. KEYCAPE_TEST_ISSUER="$ISSUER_URL" \ go -C src test ./tests/conformance/... -v -count=1 echo "=== Scenario B PASSED ===" echo "Note: this proves the migrated realm serves a conforming OIDC surface." echo "It does not prove credential, MFA or relying-party behaviour was preserved."