"""HaulProof webhook receiver for Python 3.8+ (standard library only): checks X-HaulProof-Signature over the raw body and refuses timestamps older than 5 minutes (replays). Usage: HP_WEBHOOK_SECRET=whsec_... PORT=8080 python verify_webhook.py""" import hashlib, hmac, json, os, time from http.server import BaseHTTPRequestHandler, HTTPServer SECRET = os.environ["HP_WEBHOOK_SECRET"].encode() def verify(raw: bytes, timestamp: str, signature: str, secret: bytes = SECRET, now: float = None) -> bool: if not (timestamp or "").isdigit() or abs((now or time.time()) - int(timestamp)) > 300: return False want = "sha256=" + hmac.new(secret, timestamp.encode() + b"." + raw, hashlib.sha256).hexdigest() return hmac.compare_digest(want, signature or "") class Hook(BaseHTTPRequestHandler): def do_POST(self): raw = self.rfile.read(int(self.headers.get("Content-Length", "0"))) if not verify(raw, self.headers.get("X-HaulProof-Timestamp"), self.headers.get("X-HaulProof-Signature")): self.send_response(401); self.end_headers(); return msg = json.loads(raw) d = msg["data"] print(msg["event"], "(test)" if msg.get("test") else "", d["type"], d["severity"], d["carrier"]["key"], d["carrier"]["name"], flush=True) self.send_response(204); self.end_headers() def log_message(self, *args): pass if __name__ == "__main__": HTTPServer(("", int(os.environ.get("PORT", "8080"))), Hook).serve_forever()