RAILIANCE-WP-0011-T04: smoke checks unsigned 401, signed no-op 200, ESO Ready, and /v1/federated; point operator docs at platform rotation runbook.
87 lines
No EOL
2.9 KiB
Bash
Executable file
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 ]] |