diff --git a/sso-mfa/k8s/keycape/README.md b/sso-mfa/k8s/keycape/README.md index 2d35b2e..235ad4e 100644 --- a/sso-mfa/k8s/keycape/README.md +++ b/sso-mfa/k8s/keycape/README.md @@ -135,7 +135,9 @@ bash ./verify-openbao-client.sh ``` The patch script preserves existing secret values and does not print the -decoded `config.yaml` or signing key. +decoded `config.yaml` or signing key. The verifier checks the live Secret and +then opens a short local `kubectl port-forward` to KeyCape; it does not require +`curl` or `wget` inside the KeyCape container image. Example entry (public client, PKCE, for a SPA): ```yaml diff --git a/sso-mfa/k8s/keycape/verify-openbao-client.sh b/sso-mfa/k8s/keycape/verify-openbao-client.sh index 0ab920c..1bc1085 100644 --- a/sso-mfa/k8s/keycape/verify-openbao-client.sh +++ b/sso-mfa/k8s/keycape/verify-openbao-client.sh @@ -7,6 +7,7 @@ set -euo pipefail NAMESPACE="${KEYCAPE_NAMESPACE:-sso}" SECRET="${KEYCAPE_CONFIG_SECRET:-keycape-config}" KUBECTL="${KUBECTL:-kubectl}" +PORT="${KEYCAPE_VERIFY_PORT:-18080}" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" "$KUBECTL" get secret "$SECRET" -n "$NAMESPACE" -o json \ @@ -22,7 +23,43 @@ if [[ -z "$KC_POD" ]]; then exit 1 fi -"$KUBECTL" exec -n "$NAMESPACE" "$KC_POD" -- \ - wget -qO- "http://localhost:8080/.well-known/openid-configuration" >/dev/null +PF_LOG="${TMPDIR:-/tmp}/netkingdom-keycape-openbao-client-port-forward.log" +rm -f "$PF_LOG" -echo "[PASS] KeyCape discovery endpoint responds from pod $KC_POD" +"$KUBECTL" -n "$NAMESPACE" port-forward --address 127.0.0.1 svc/keycape "$PORT:8080" \ + >"$PF_LOG" 2>&1 & +PF_PID=$! + +cleanup() { + kill "$PF_PID" 2>/dev/null || true + wait "$PF_PID" 2>/dev/null || true +} +trap cleanup EXIT + +for _ in $(seq 1 30); do + if python3 - "$PORT" <<'PY' >/dev/null 2>&1 +import json +import sys +import urllib.request + +port = sys.argv[1] +with urllib.request.urlopen(f"http://127.0.0.1:{port}/.well-known/openid-configuration", timeout=2) as response: + payload = json.load(response) +if not payload.get("issuer"): + raise SystemExit("missing issuer") +PY + then + echo "[PASS] KeyCape discovery endpoint responds via local port-forward to pod $KC_POD" + exit 0 + fi + if ! kill -0 "$PF_PID" 2>/dev/null; then + echo "[FAIL] KeyCape port-forward exited before discovery responded" >&2 + cat "$PF_LOG" >&2 + exit 1 + fi + sleep 1 +done + +echo "[FAIL] KeyCape discovery endpoint did not respond via local port-forward" >&2 +cat "$PF_LOG" >&2 +exit 1 diff --git a/workplans/NET-WP-0015-platform-root-custody-and-openbao-identity-bootstrap.md b/workplans/NET-WP-0015-platform-root-custody-and-openbao-identity-bootstrap.md index 6129e2d..05ec382 100644 --- a/workplans/NET-WP-0015-platform-root-custody-and-openbao-identity-bootstrap.md +++ b/workplans/NET-WP-0015-platform-root-custody-and-openbao-identity-bootstrap.md @@ -333,6 +333,12 @@ decrypted bootstrap secrets after the operator correctly hit the absent verifier for the `openbao-admin` client so this non-secret client addition can be applied without decrypting the full bootstrap secret bundle. +**2026-05-26:** Fixed the focused KeyCape OpenBao verifier after the live +KeyCape image lacked `wget`. The verifier now checks the live Secret and then +uses a short local `kubectl port-forward` plus Python HTTP request for OIDC +discovery, avoiding assumptions about tools installed inside the KeyCape +container. + **2026-05-24:** Stepped back from ad hoc secret rollout and added the custodian age-key bootstrap model to the control surface. The UI now records the custodian public age recipient, a derived fingerprint, and a non-secret