Newer
Older
openstack-caracal-ipv4 / tests / claude-guard / run-tests.sh
#!/usr/bin/env bash
# tests/claude-guard/run-tests.sh -- offline harness for the Claude Code
# PreToolUse guard (.claude/hooks/guard-destructive.py). Proves each NEVER
# rule blocks (exit 2) and normal ops pass (exit 0), including the malformed-
# input fail-open-to-permission-rules contract. ASCII + LF.
set -uo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
HOOK="$(cd "$HERE/../.." && pwd)/.claude/hooks/guard-destructive.py"
PASS=0; FAIL=0
run() { # run <want_rc> <label> <json-or-raw>
  local rc
  printf '%s' "$3" | python3 "$HOOK" >/dev/null 2>&1; rc=$?
  if [ "$rc" = "$1" ]; then echo "  PASS  $2"; PASS=$((PASS+1))
  else echo "  FAIL  $2 (rc=$rc want=$1)"; FAIL=$((FAIL+1)); fi
}
cmd() { printf '{"tool_input":{"command":"%s"}}' "$1"; }

run 2 "vault operator init blocked"            "$(cmd 'vault operator init > /tmp/x 2>&1')"
run 2 "vault operator rekey blocked"           "$(cmd 'VAULT_ADDR=x vault operator rekey')"
run 2 "destroy-controller blocked"             "$(cmd 'juju destroy-controller maas-controller')"
run 2 "maas list blocked (DOCFIX-016)"         "$(cmd 'maas list')"
run 2 "force-push blocked"                     "$(cmd 'git push --force origin main')"
run 2 "secret read blocked (vault-init)"       "$(cmd 'cat ~/vault-init/unseal-keys.txt')"
run 2 "secret read blocked (appcred)"          "$(cmd 'head -1 /home/j/tenant-acme/acme-svc-appcred.txt')"
run 2 "catastrophic rm blocked"                "$(cmd 'rm -rf /')"
run 0 "juju status passes"                     "$(cmd 'juju status -m openstack --format=json')"
run 0 "cloud-assert passes"                    "$(cmd 'bash scripts/cloud-assert.sh')"
run 0 "vault status (non-one-shot) passes"     "$(cmd 'juju ssh vault/0 -- vault status')"
run 0 "maas admin read passes (not maas list)" "$(cmd 'maas admin machines read')"
run 0 "malformed input -> no opinion (rc 0)"   'not-json-at-all'

echo; echo "RESULT: PASS=$PASS FAIL=$FAIL"
[ "$FAIL" -eq 0 ] && { echo "ALL PASS"; exit 0; } || exit 1