Files
haproxy-manager-base/templates/hap_coraza_spoa_backend.tpl
Josh Knapp ba4c101135
All checks were successful
HAProxy Manager Build and Push / Build-and-Push (push) Successful in 55s
fix(coraza): add deny rules that act on Coraza's verdict + spop-check on backend
Two fixes that complete the SPOE enforcement path:

1. Listener was sending requests to Coraza for inspection but never reading
   the result. Coraza-SPOA sets var(txn.coraza.action) to "deny" / "drop"
   / "redirect" when a rule with that disruptive action fires; HAProxy
   needs explicit rules that READ the variable and apply the action.
   Without them, the audit log shows "Access denied" but the request
   still gets HTTP 200 (verified on staging: sqlmap/JNDI/shellinj all
   detected, all returned 200).

   Added the standard six rules from upstream's example/haproxy/haproxy.cfg
   covering http-request + http-response phases for each of deny/drop/
   redirect. Same set the upstream Coraza-SPOA docs recommend.

   Intentionally did NOT add the upstream's fail-CLOSED rule
   `http-request deny deny_status 500 if { var(txn.coraza.error) -m int gt 0 }`
   — for a hosting platform we want fail-open. Documented inline.

2. Backend health check switched from plain TCP `check` to `option
   spop-check`. The spop-check actually negotiates a SPOE session against
   the agent, so HAProxy detects a half-broken SPOA that's listening on
   :9000 but failing protocol handshakes. Plain `check` would miss that.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 17:16:03 -07:00

17 lines
804 B
Smarty

# Coraza-SPOA backend.
# Only rendered into haproxy.cfg when HAPROXY_CORAZA_SPOE_BACKEND env var is
# set on the haproxy-manager container. SPOE traffic to this backend is TCP,
# not HTTP. The agent target comes from the env var so a single image can be
# deployed against different sidecar host:port pairs (typically the sidecar
# container's name + 9000 inside the shared docker network).
backend coraza-spoa-backend
mode tcp
# spop-check actually speaks the SPOE protocol against the agent —
# confirms the agent can negotiate a session, not just that the TCP
# port is open. Required to detect a half-broken SPOA that's listening
# but not actually processing.
option spop-check
timeout connect 5s
timeout server 30s
server coraza-spoa {{ agent_target }} check