first commit

This commit is contained in:
2026-06-09 17:31:10 -07:00
commit babfcb8666
7 changed files with 3298 additions and 0 deletions
BIN
View File
Binary file not shown.
+223
View File
@@ -0,0 +1,223 @@
#!/usr/bin/env python3
import base64
import hashlib
import hmac
import json
import os
import re
import secrets
import sys
import time
from dataclasses import dataclass
from typing import Any, Dict, Optional
from urllib.parse import urlparse
import requests
@dataclass
class FlareConfig:
src_url: str
get_base_url: str
post_url: str
wrapper_sh_url: str
wrapper_bash_url: str
wrapper_ps1_url: str
dashboard_url: str
flare_html_url: str
events_url: str
topic: str
token: str
secret: str
def strip_query_fragment(url: str) -> str:
return url.split("#", 1)[0].split("?", 1)[0]
def derive_get_base(src_url: str) -> str:
clean = strip_query_fragment(src_url).rstrip("/")
for suffix in ("/wrapper.sh", "/wrapper.bash", "/wrapper.ps1"):
if clean.endswith(suffix):
return clean[: -len(suffix)]
return clean.rsplit("/", 1)[0]
def parse_wrapper_exports(wrapper_text: str) -> Dict[str, str]:
exports: Dict[str, str] = {}
patterns = [
re.compile(r'^export\s+(FLARE_[A-Z_]+)="([^"]*)"$', re.MULTILINE),
re.compile(r'^\$env:(FLARE_[A-Z_]+)\s*=\s*"([^"]*)"$', re.MULTILINE),
]
for pattern in patterns:
for key, value in pattern.findall(wrapper_text):
exports[key] = value
return exports
def load_config_from_src(src_url: str) -> FlareConfig:
get_base_url = derive_get_base(src_url)
wrapper = requests.get(src_url, timeout=10)
wrapper.raise_for_status()
exports = parse_wrapper_exports(wrapper.text)
post_url = (exports.get("FLARE_URL") or "").rstrip("/")
topic = exports.get("FLARE_TOPIC", "")
token = exports.get("FLARE_TOKEN", "")
secret = exports.get("FLARE_SECRET", "")
return FlareConfig(
src_url=src_url,
get_base_url=get_base_url,
post_url=post_url,
wrapper_sh_url=f"{get_base_url}/wrapper.sh",
wrapper_bash_url=f"{get_base_url}/wrapper.bash",
wrapper_ps1_url=f"{get_base_url}/wrapper.ps1",
dashboard_url=f"{get_base_url}/",
flare_html_url=f"{get_base_url}/flare.html",
events_url=f"{get_base_url}/events",
topic=topic,
token=token,
secret=secret,
)
def create_signed_payload(topic: str, title: str, detail: Optional[Dict[str, Any]] = None, secret: str = "") -> Dict[str, Any]:
detail = detail or {}
content = {
"complete": 0,
"detail": detail,
"error": 0,
"host": "test-runner",
"seq": int(time.time() * 1000) & 0xFFFFFFFF,
"timestamp": int(time.time()),
"title": title,
"topic": topic,
}
envelope: Dict[str, Any] = {"content": content}
if secret:
canon = json.dumps(content, sort_keys=True, separators=(",", ":"), ensure_ascii=False)
nonce = secrets.token_hex(16)
mac = hmac.new(secret.encode("utf-8"), (canon + nonce).encode("utf-8"), hashlib.sha256).hexdigest()
envelope["nonce"] = nonce
envelope["hmac"] = mac
return {
"topic": topic,
"title": title,
"message": json.dumps(envelope, separators=(",", ":"), ensure_ascii=False),
"tags": ["test"],
"priority": 3,
}
def auth_headers(token: str, extra: Optional[Dict[str, str]] = None) -> Dict[str, str]:
headers = dict(extra or {})
if token:
headers["Authorization"] = f"Bearer {token}"
return headers
def run_case(
description: str,
method: str,
url: str,
*,
expected_status: int,
headers: Optional[Dict[str, str]] = None,
params: Optional[Dict[str, str]] = None,
json_body: Optional[Any] = None,
data: Optional[Any] = None,
stream: bool = False,
) -> bool:
try:
response = requests.request(
method=method,
url=url,
headers=headers,
params=params,
json=json_body,
data=data,
timeout=8,
stream=stream,
)
ok = response.status_code == expected_status
status = "PASS" if ok else f"FAIL ({response.status_code})"
print(f"{status:<12} {method:<7} {response.request.path_url:<46} {description}")
if stream:
response.close()
return ok
except Exception as exc:
print(f"ERROR {method:<7} {url:<46} {description}: {exc}")
return False
def main() -> int:
src_url = os.environ.get("__FLARE_SRC", "").strip()
if not src_url:
print("ERROR: __FLARE_SRC is required", file=sys.stderr)
return 1
cfg = load_config_from_src(src_url)
root = f"{urlparse(cfg.get_base_url).scheme}://{urlparse(cfg.get_base_url).netloc}"
bad_post = root + "/definitely-not-real-post-path"
print("Resolved Flare test target")
print(f" src : {cfg.src_url}")
print(f" get base : {cfg.get_base_url}")
print(f" post target : {cfg.post_url}")
print(f" dashboard : {cfg.dashboard_url}")
print(f" events : {cfg.events_url}")
print(f" topic : {cfg.topic or '<missing>'}")
print(f" token present : {'yes' if cfg.token else 'no'}")
print(f" secret present: {'yes' if cfg.secret else 'no'}")
print()
print(f"{'RESULT':<12} {'METHOD':<7} {'PATH':<46} DESCRIPTION")
print("-" * 100)
all_ok = True
all_ok &= run_case("dashboard index", "GET", cfg.dashboard_url, expected_status=200)
all_ok &= run_case("dashboard HTML with extra query", "GET", cfg.flare_html_url, expected_status=200, params={"junk": "1"})
all_ok &= run_case("wrapper.sh fetch", "GET", cfg.wrapper_sh_url, expected_status=200)
all_ok &= run_case("wrapper.bash fetch", "GET", cfg.wrapper_bash_url, expected_status=200)
all_ok &= run_case("wrapper.ps1 fetch", "GET", cfg.wrapper_ps1_url, expected_status=200)
all_ok &= run_case("root path stays dark", "GET", root + "/", expected_status=404)
all_ok &= run_case("weird GET path under root", "GET", root + "/definitely-not-real", expected_status=404)
all_ok &= run_case("unsupported HEAD currently returns 501", "HEAD", cfg.dashboard_url, expected_status=501)
all_ok &= run_case("CORS preflight on POST target", "OPTIONS", cfg.post_url, expected_status=204)
all_ok &= run_case("events without auth rejected", "GET", cfg.events_url, expected_status=401, params={"topic": cfg.topic}, stream=True)
all_ok &= run_case("events with bearer auth", "GET", cfg.events_url, expected_status=200, headers=auth_headers(cfg.token), params={"topic": cfg.topic}, stream=True)
all_ok &= run_case("events history via since=all", "GET", cfg.events_url, expected_status=200, headers=auth_headers(cfg.token), params={"topic": cfg.topic, "since": "all"}, stream=True)
if cfg.token:
auth_b64 = base64.b64encode(f"Bearer {cfg.token}".encode("utf-8")).decode("ascii")
all_ok &= run_case("events with auth query param", "GET", cfg.events_url, expected_status=200, params={"topic": cfg.topic, "auth": auth_b64}, stream=True)
all_ok &= run_case("POST missing auth rejected", "POST", cfg.post_url, expected_status=401, json_body={"topic": cfg.topic})
all_ok &= run_case("POST bad bearer rejected", "POST", cfg.post_url, expected_status=401, headers=auth_headers("definitely-wrong-token"), json_body={"topic": cfg.topic})
all_ok &= run_case("POST invalid JSON rejected", "POST", cfg.post_url, expected_status=400, headers=auth_headers(cfg.token, {"Content-Type": "application/json"}), data="{not-json")
all_ok &= run_case("POST missing topic rejected", "POST", cfg.post_url, expected_status=400, headers=auth_headers(cfg.token), json_body={"title": "no topic"})
all_ok &= run_case("POST wrong path rejected", "POST", bad_post, expected_status=404, headers=auth_headers(cfg.token), json_body={"topic": cfg.topic})
if cfg.secret:
all_ok &= run_case("POST bad HMAC rejected", "POST", cfg.post_url, expected_status=400, headers=auth_headers(cfg.token), json_body=create_signed_payload(cfg.topic, "bad hmac", {"status": "bad"}, secret="wrong-secret"))
all_ok &= run_case("POST valid signed event", "POST", cfg.post_url, expected_status=200, headers=auth_headers(cfg.token), json_body=create_signed_payload(cfg.topic, "valid signed", {"status": "ok"}, secret=cfg.secret))
all_ok &= run_case("POST signed flare-summary event", "POST", cfg.post_url, expected_status=200, headers=auth_headers(cfg.token), json_body=create_signed_payload(cfg.topic, "flare-summary", {"phase": "http_test", "status": "summary-ok"}, secret=cfg.secret))
else:
all_ok &= run_case("POST unsigned event in no-secret mode", "POST", cfg.post_url, expected_status=200, headers=auth_headers(cfg.token), json_body=create_signed_payload(cfg.topic, "unsigned allowed", {"status": "ok"}, secret=""))
all_ok &= run_case("PUT unsupported method returns 501", "PUT", cfg.post_url, expected_status=501, headers=auth_headers(cfg.token), json_body={"topic": cfg.topic})
print("-" * 100)
if all_ok:
print("All HTTP tests passed.")
return 0
print("One or more HTTP tests failed.")
return 1
if __name__ == "__main__":
raise SystemExit(main())
+99
View File
@@ -0,0 +1,99 @@
#!/usr/bin/env bash
set -uo pipefail
require_env() {
local name="$1"
if [[ -z "${!name:-}" ]]; then
echo "ERROR: $name is required" >&2
exit 1
fi
}
strip_query_fragment() {
local s="$1"
s="${s%%\#*}"
s="${s%%\?*}"
printf '%s' "$s"
}
derive_wrapper_urls() {
local src clean base
src="$1"
clean="$(strip_query_fragment "$src")"
case "$clean" in
*/wrapper.sh) base="${clean%/wrapper.sh}" ;;
*/wrapper.bash) base="${clean%/wrapper.bash}" ;;
*/wrapper.ps1) base="${clean%/wrapper.ps1}" ;;
*/) base="${clean%/}" ;;
*) base="${clean%/*}" ;;
esac
WRAPPER_SH_URL="$base/wrapper.sh"
WRAPPER_BASH_URL="$base/wrapper.bash"
}
run_case() {
local desc="$1"
shift
printf 'Test: %-46s' "$desc"
if "$@"; then
echo "✅ PASS"
else
local rc=$?
echo "❌ FAIL (rc=$rc)"
return "$rc"
fi
}
exercise_wrapper() {
local label="$1"
local src_url="$2"
(
set +u
eval "$(curl -fsSL "$src_url")" || exit 90
command -v mon >/dev/null || exit 91
command -v mon_detail >/dev/null || exit 92
command -v mon_complete >/dev/null || exit 93
command -v mon_error >/dev/null || exit 94
mon_detail "flare-summary" '{"source":"src_test","wrapper":"'"$label"'","phase":"bootstrap"}' || exit 100
sleep 0.2
mon "${label}: starting" || exit 101
sleep 0.2
mon_detail "${label}: detail blob" '{"nginx":"1.18.0","openssl":"3.0.2"}' || exit 102
sleep 0.2
mon_complete "${label}: completed task" || exit 103
sleep 0.2
mon_error "${label}: error case" || exit 104
sleep 0.2
mon "${label}: manual title" || exit 105
)
}
main() {
require_env "__FLARE_SRC"
derive_wrapper_urls "$__FLARE_SRC"
echo "Using source seed : $__FLARE_SRC"
echo "Derived wrapper.sh : $WRAPPER_SH_URL"
echo "Derived wrapper.bash: $WRAPPER_BASH_URL"
echo
local failures=0
run_case "source wrapper.sh then use functions" exercise_wrapper "wrapper.sh" "$WRAPPER_SH_URL" || ((failures+=1))
run_case "source wrapper.bash then use functions" exercise_wrapper "wrapper.bash" "$WRAPPER_BASH_URL" || ((failures+=1))
echo
if (( failures == 0 )); then
echo "🏁 All wrapper-source tests passed."
else
echo "🏁 Completed with $failures failing test group(s)."
exit 1
fi
}
main "$@"