crabbox/scripts/live-auth-smoke.sh
2026-05-02 03:25:12 +01:00

143 lines
4.5 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
if [[ "${CRABBOX_LIVE:-}" != "1" ]]; then
echo "set CRABBOX_LIVE=1 to run live coordinator auth smoke tests" >&2
exit 2
fi
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cb="${CRABBOX_BIN:-$root/bin/crabbox}"
coord="${CRABBOX_AUTH_SMOKE_COORDINATOR:-${CRABBOX_COORDINATOR:-https://crabbox-access.openclaw.ai}}"
config_path="$("$cb" config path)"
need_tool() {
if ! command -v "$1" >/dev/null 2>&1; then
echo "missing required tool: $1" >&2
exit 2
fi
}
need_tool curl
need_tool jq
need_tool ruby
config_value() {
local key_path="$1"
ruby -ryaml -e '
value = ARGV[1].split(".").reduce(YAML.load_file(ARGV[0])) do |memo, key|
memo.is_a?(Hash) ? memo[key] : nil
end
exit 3 if value.nil? || value.to_s.empty?
print value
' "$config_path" "$key_path"
}
curl_quote() {
ruby -e 'print ARGV[0].inspect' "$1"
}
write_curl_config() {
local token="$1"
local url="$2"
local output="$3"
shift 3
: >"$output"
chmod 0600 "$output"
{
printf 'url = %s\n' "$(curl_quote "$url")"
printf 'request = "GET"\n'
printf 'connect-timeout = "10"\n'
printf 'max-time = "300"\n'
printf 'silent\n'
printf 'show-error\n'
printf 'location\n'
printf 'output = "-"\n'
printf 'write-out = "\\n%%{http_code}"\n'
printf 'header = %s\n' "$(curl_quote "Authorization: Bearer $token")"
if [[ -n "${access_client_id:-}" && -n "${access_client_secret:-}" ]]; then
printf 'header = %s\n' "$(curl_quote "CF-Access-Client-Id: $access_client_id")"
printf 'header = %s\n' "$(curl_quote "CF-Access-Client-Secret: $access_client_secret")"
fi
for header in "$@"; do
printf 'header = %s\n' "$(curl_quote "$header")"
done
} >>"$output"
}
request_json() {
local token="$1"
local path="$2"
local body_file="$3"
shift 3
local cfg
cfg="$(mktemp)"
write_curl_config "$token" "${coord%/}$path" "$cfg" "$@"
local response
response="$(curl --config "$cfg")"
rm -f "$cfg"
local status="${response##*$'\n'}"
local body="${response%$'\n'*}"
printf '%s' "$body" >"$body_file"
printf '%s' "$status"
}
shared_token="$(config_value broker.token)"
admin_token="$(config_value broker.adminToken)"
access_client_id="${CRABBOX_ACCESS_CLIENT_ID:-$(config_value broker.access.clientId 2>/dev/null || true)}"
access_client_secret="${CRABBOX_ACCESS_CLIENT_SECRET:-$(config_value broker.access.clientSecret 2>/dev/null || true)}"
owner="${CRABBOX_OWNER:-$(git config user.email 2>/dev/null || true)}"
owner="${owner:-crabbox-auth-smoke@example.invalid}"
org="${CRABBOX_ORG:-openclaw}"
if [[ "$coord" == *"crabbox-access.openclaw.ai"* ]]; then
no_access_code="$(curl -sS -o /dev/null -w '%{http_code}' "${coord%/}/v1/health")"
if [[ "$no_access_code" != "403" ]]; then
echo "failed no-access edge check: HTTP $no_access_code" >&2
exit 1
fi
echo "ok no-access edge denied http=403"
fi
whoami="$(env -u CRABBOX_COORDINATOR_TOKEN CRABBOX_COORDINATOR="$coord" "$cb" whoami --json)"
printf '%s\n' "$whoami" | jq -e '.auth == "bearer" and (.owner | length > 0) and (.org | length > 0)' >/dev/null
echo "ok shared token whoami owner=$(printf '%s\n' "$whoami" | jq -r '.owner') org=$(printf '%s\n' "$whoami" | jq -r '.org')"
body="$(mktemp)"
trap 'rm -f "$body"' EXIT
status="$(request_json "$shared_token" "/v1/whoami" "$body" \
"X-Crabbox-Owner: $owner" \
"X-Crabbox-Org: $org" \
"cf-access-authenticated-user-email: spoof@example.invalid")"
if [[ "$status" != "200" ]]; then
echo "failed raw Access spoof check: HTTP $status body=$(cat "$body")" >&2
exit 1
fi
spoof_owner="$(jq -r '.owner' "$body")"
if [[ "$spoof_owner" == "spoof@example.invalid" ]]; then
echo "failed raw Access spoof check: spoofed owner accepted" >&2
exit 1
fi
echo "ok raw Access identity spoof ignored owner=$spoof_owner"
status="$(request_json "$shared_token" "/v1/admin/leases?limit=1" "$body" \
"X-Crabbox-Owner: $owner" \
"X-Crabbox-Org: $org")"
if [[ "$status" != "403" ]]; then
echo "failed shared-token admin denial: HTTP $status body=$(cat "$body")" >&2
exit 1
fi
jq -e '.message == "admin token required"' "$body" >/dev/null
echo "ok shared token denied for admin http=403"
status="$(request_json "$admin_token" "/v1/admin/leases?limit=1" "$body" \
"X-Crabbox-Owner: $owner" \
"X-Crabbox-Org: $org")"
if [[ "$status" != "200" ]]; then
echo "failed admin-token admin check: HTTP $status body=$(cat "$body")" >&2
exit 1
fi
jq -e '.leases | type == "array"' "$body" >/dev/null
echo "ok admin token accepted for admin leases=$(jq '.leases | length' "$body")"