All checks were successful
HAProxy Manager Build and Push / Build-and-Push (push) Successful in 55s
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>