#!/usr/bin/env bash # Production policy-gate smoke for WARDEN-WP-0009 T02. # # Validates flex-auth registry (from inventory), allow/deny paths through # warden sign, and optionally OpenBao-backed signing when VAULT_TOKEN works. # # Usage: # ./scripts/policy_gate_production_smoke.sh # INVENTORY=~/.config/warden/inventory.yaml ./scripts/policy_gate_production_smoke.sh # SMOKE_VAULT=1 ./scripts/policy_gate_production_smoke.sh # also test backend: vault set -euo pipefail ROOT="$(cd "$(dirname "$0")/.." && pwd)" INVENTORY="${INVENTORY:-$HOME/.config/warden/inventory.yaml}" REGISTRY="$ROOT/registry/flex-auth/production_registry_snapshot.json" POLICY="${FLEX_AUTH_POLICY:-$HOME/flex-auth/examples/ops-warden/policy_package.md}" FLEX_AUTH_BIN="${FLEX_AUTH_BIN:-/tmp/flex-auth}" ADDR="${FLEX_AUTH_ADDR:-127.0.0.1:18090}" PUBKEY="${PUBKEY:-$HOME/.ssh/agt-state-hub-bridge_ed25519.pub}" ACTOR="${ACTOR:-agt-state-hub-bridge}" SMOKE_DIR="$(mktemp -d /tmp/warden-prod-policy-smoke-XXXXXX)" cleanup() { if [[ -n "${FA_PID:-}" ]] && kill -0 "$FA_PID" 2>/dev/null; then kill "$FA_PID" 2>/dev/null || true wait "$FA_PID" 2>/dev/null || true fi } trap cleanup EXIT echo "==> Building registry from $INVENTORY" uv run --directory "$ROOT" python scripts/build_flex_auth_registry.py \ "$INVENTORY" -o "$REGISTRY" "$FLEX_AUTH_BIN" load-registry --file "$REGISTRY" >/dev/null echo "==> Starting flex-auth on $ADDR" "$FLEX_AUTH_BIN" serve \ --addr "$ADDR" \ --registry "$REGISTRY" \ --policy "$POLICY" \ --log "$SMOKE_DIR/flex-auth-decisions.jsonl" & FA_PID=$! sleep 0.6 ssh-keygen -t ed25519 -f "$SMOKE_DIR/ca_key" -N "" -q cat >"$SMOKE_DIR/warden.yaml" < Allow path: warden sign $ACTOR" uv run --directory "$ROOT" warden sign "$ACTOR" --pubkey "$PUBKEY" >/dev/null ALLOW_LINE="$(tail -1 "$SMOKE_DIR/state/signatures.log")" python3 -c "import json,sys; e=json.loads(sys.argv[1]); assert e.get('policy_decision_id'), e; print('policy_decision_id:', e['policy_decision_id'])" "$ALLOW_LINE" echo "==> Deny path: ttl above max" set +e DENY_OUT="$(uv run --directory "$ROOT" warden sign "$ACTOR" --pubkey "$PUBKEY" --ttl 999 2>&1)" DENY_RC=$? set -e if [[ "$DENY_RC" -ne 1 ]]; then echo "expected deny exit 1, got $DENY_RC" >&2 exit 1 fi echo "$DENY_OUT" | grep -q "ttl_out_of_bounds" if [[ "${SMOKE_VAULT:-0}" == "1" ]]; then echo "==> Vault-backed allow (requires scoped VAULT_TOKEN)" cat >"$SMOKE_DIR/warden-vault.yaml" </dev/null VAULT_LINE="$(tail -1 "$SMOKE_DIR/state-vault/signatures.log")" python3 -c "import json,sys; e=json.loads(sys.argv[1]); assert e.get('backend')=='vault' and e.get('policy_decision_id'); print('vault policy_decision_id:', e['policy_decision_id'])" "$VAULT_LINE" fi echo "OK — production registry policy gate smoke passed"