Files

96 lines
3.0 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
# Smoke a deployed managed Control Panel endpoint.
#
# Required:
# CASAN_CP_BASE_URL=https://control-panel.example.com
#
# Optional:
# CASAN_CP_COOKIE_JAR=/path/to/cookies.txt # authenticated browser/session cookie jar
# CASAN_CP_ALLOW_INSECURE=1 # only for local labs/self-signed certs
#
# Without a cookie jar this proves auth is enforced. With a cookie jar it also proves
# the API identity mapping and Command Center contract behind the auth proxy.
BASE="${CASAN_CP_BASE_URL:-}"
COOKIE_JAR="${CASAN_CP_COOKIE_JAR:-}"
fail() {
echo "CP_MANAGED_SMOKE_FAIL $1"
exit 1
}
[[ -n "$BASE" ]] || fail "missing_base_url env=CASAN_CP_BASE_URL"
BASE="${BASE%/}"
if [[ "$BASE" != https://* && "${CASAN_CP_ALLOW_INSECURE:-0}" != "1" ]]; then
fail "base_url_must_be_https"
fi
CURL=(curl -sS)
if [[ "${CASAN_CP_ALLOW_INSECURE:-0}" == "1" ]]; then
CURL+=(-k)
fi
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT
root_code="$("${CURL[@]}" -o "$tmp/root.html" -w "%{http_code}" "$BASE/" || true)"
if [[ "$root_code" == "200" ]]; then
fail "unauth_root_returned_200"
fi
spoof_code="$("${CURL[@]}" \
-H 'X-CASAN-Actor: spoofed-admin' \
-H 'X-CASAN-Role: org-admin' \
-H 'X-CASAN-Groups: casan-org-admin' \
-o "$tmp/spoof.json" \
-w "%{http_code}" \
"$BASE/api/v1/settings" || true)"
if [[ "$spoof_code" == "200" ]]; then
fail "spoofed_identity_bypass"
fi
if [[ -z "$COOKIE_JAR" ]]; then
echo "CP_MANAGED_SMOKE_PARTIAL unauth_protected=true spoof_blocked=true authenticated=false"
exit 0
fi
[[ -f "$COOKIE_JAR" ]] || fail "missing_cookie_jar path=$COOKIE_JAR"
settings_code="$("${CURL[@]}" -L -b "$COOKIE_JAR" -c "$COOKIE_JAR" \
-o "$tmp/settings.json" -w "%{http_code}" "$BASE/api/v1/settings" || true)"
if [[ "$settings_code" != "200" ]]; then
cat "$tmp/settings.json" || true
fail "settings_http=$settings_code"
fi
command_code="$("${CURL[@]}" -L -b "$COOKIE_JAR" -c "$COOKIE_JAR" \
-o "$tmp/command.json" -w "%{http_code}" "$BASE/api/v1/command" || true)"
if [[ "$command_code" != "200" ]]; then
cat "$tmp/command.json" || true
fail "command_http=$command_code"
fi
python3 - "$tmp/settings.json" "$tmp/command.json" <<'PY'
import json
import sys
settings = json.load(open(sys.argv[1]))
assert settings.get("success") is True, settings
actor = settings.get("data", {}).get("actor", {})
assert actor.get("actor") and actor.get("actor") != "anonymous", actor
assert actor.get("role") and actor.get("role") != "unknown", actor
command = json.load(open(sys.argv[2]))
assert command.get("success") is True, command
widgets = command.get("data", {}).get("widgets", {})
assert len(widgets) == 9, widgets.keys()
assert "chat_loop" in widgets, widgets.keys()
for widget in widgets.values():
envelope = widget.get("envelope", {})
required = {"source", "artifact_path", "commit", "run_at", "verified", "status"}
assert required <= set(envelope), envelope
print(f"CP_MANAGED_SMOKE_PASS actor={actor.get('actor')} role={actor.get('role')} widgets={len(widgets)}")
PY