95 lines
2.9 KiB
Bash
Executable File
95 lines
2.9 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) == 8, 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
|