railiance-apps/tools/reuse-webhook-smoke.sh
tegwick 0968f1d5d5
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
Add reuse-webhook-smoke and rotation runbook links
RAILIANCE-WP-0011-T04: smoke checks unsigned 401, signed no-op 200, ESO Ready,
and /v1/federated; point operator docs at platform rotation runbook.
2026-07-08 00:01:21 +02:00

87 lines
No EOL
2.9 KiB
Bash
Executable file

#!/usr/bin/env bash
# Smoke checks for reuse-surface Forgejo webhook receiver (RAILIANCE-WP-0011-T04).
# Uses the live cluster Secret for HMAC — never prints the secret value.
set -euo pipefail
REUSE_URL="${REUSE_URL:-https://reuse.coulomb.social}"
WEBHOOK_PATH="${REUSE_WEBHOOK_PATH:-/v1/webhooks/forgejo}"
KUBECONFIG_PATH="${KUBECONFIG:-$HOME/.kube/config-hosteurope}"
SECRET_NS="${REUSE_SECRET_NAMESPACE:-reuse}"
SECRET_NAME="${REUSE_SECRET_NAME:-reuse-surface-env}"
SECRET_KEY="${REUSE_WEBHOOK_SECRET_KEY:-REUSE_SURFACE_FORGEJO_WEBHOOK_SECRET}"
pass=0
fail=0
ok() { echo " PASS $*"; pass=$((pass + 1)); }
bad() { echo " FAIL $*" >&2; fail=$((fail + 1)); }
echo "reuse-surface webhook smoke — ${REUSE_URL}${WEBHOOK_PATH}"
echo "kubeconfig: ${KUBECONFIG_PATH}"
echo
unsigned_code="$(
curl -sS -o /dev/null -w "%{http_code}" -X POST \
"${REUSE_URL}${WEBHOOK_PATH}" \
-H "Content-Type: application/json" -d '{}' 2>/dev/null || true
)"
unsigned_code="${unsigned_code:-000}"
if [[ "${unsigned_code}" == "401" ]]; then
ok "unsigned POST returns 401"
else
bad "unsigned POST expected 401, got ${unsigned_code}"
fi
if kubectl --kubeconfig "${KUBECONFIG_PATH}" get externalsecret reuse-surface-runtime \
-n "${SECRET_NS}" -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}' 2>/dev/null \
| grep -q True; then
ok "ExternalSecret reuse-surface-runtime Ready"
else
bad "ExternalSecret reuse-surface-runtime not Ready"
fi
export REUSE_URL WEBHOOK_PATH KUBECONFIG_PATH SECRET_NS SECRET_NAME SECRET_KEY
if python3 <<'PY'
import base64, hashlib, hmac, json, os, subprocess, sys, urllib.error, urllib.request
reuse_url = os.environ["REUSE_URL"]
webhook_path = os.environ["WEBHOOK_PATH"]
kc = os.environ["KUBECONFIG_PATH"]
ns = os.environ["SECRET_NS"]
name = os.environ["SECRET_NAME"]
key = os.environ["SECRET_KEY"]
raw = subprocess.check_output([
"kubectl", "--kubeconfig", kc, "get", "secret", name, "-n", ns,
"-o", f"jsonpath={{.data.{key}}}",
], text=True)
secret = base64.b64decode(raw).decode()
payload = {"commits": [{"added": ["README.md"], "modified": [], "removed": []}]}
body = json.dumps(payload).encode()
sig = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
req = urllib.request.Request(
f"{reuse_url.rstrip('/')}{webhook_path}",
data=body,
headers={"Content-Type": "application/json", "X-Forgejo-Signature": sig},
method="POST",
)
with urllib.request.urlopen(req, timeout=15) as resp:
data = json.loads(resp.read().decode())
if resp.status != 200 or data.get("accepted") is not False:
raise SystemExit(f"unexpected response: {data!r}")
PY
then
ok "signed no-op POST returns 200 accepted=false"
else
bad "signed no-op POST failed"
fi
if curl -fsS "${REUSE_URL}/v1/federated" -o /dev/null 2>/dev/null; then
ok "GET /v1/federated returns 200"
else
bad "GET /v1/federated failed"
fi
echo
echo "summary: ${pass} passed, ${fail} failed"
[[ "${fail}" -eq 0 ]]