#!/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