2026-05-12 16:49:29 -07:00
|
|
|
# Coraza SPOE engine configuration.
|
|
|
|
|
#
|
|
|
|
|
# Written to /etc/haproxy/coraza-spoe.cfg by haproxy_manager.generate_config()
|
|
|
|
|
# when HAPROXY_CORAZA_SPOE_BACKEND env var is set. Referenced from haproxy.cfg
|
|
|
|
|
# via `filter spoe engine coraza config /etc/haproxy/coraza-spoe.cfg`.
|
|
|
|
|
#
|
|
|
|
|
# Engine name "coraza" must match the engine name in the filter line in the
|
2026-05-12 17:12:09 -07:00
|
|
|
# main config; group name "coraza-req" must match the send-spoe-group action.
|
|
|
|
|
# Application name "haproxy" must match the application block in coraza-spoa's
|
|
|
|
|
# config.yaml.
|
|
|
|
|
#
|
|
|
|
|
# Reference: this config follows the shape from coraza-spoa's upstream
|
|
|
|
|
# example/haproxy/coraza.cfg (v0.7.1). Arg names + ordering are required by
|
|
|
|
|
# Coraza-SPOA exactly as specified — DO NOT reorder or rename without
|
|
|
|
|
# coordinating with the agent.
|
2026-05-12 16:49:29 -07:00
|
|
|
|
|
|
|
|
[coraza]
|
|
|
|
|
|
|
|
|
|
spoe-agent coraza
|
2026-05-12 17:12:09 -07:00
|
|
|
# `groups` (not `messages`) lists the spoe-group names this engine offers
|
|
|
|
|
# via `send-spoe-group` actions. The same group name appears below in a
|
|
|
|
|
# spoe-group block, which in turn references the actual message.
|
|
|
|
|
groups coraza-req
|
2026-05-12 16:49:29 -07:00
|
|
|
|
2026-05-12 17:12:09 -07:00
|
|
|
# Prefix for variables the agent sets back on the request transaction —
|
|
|
|
|
# e.g. var(txn.coraza.error) when set-on-error triggers.
|
2026-05-12 16:49:29 -07:00
|
|
|
option var-prefix coraza
|
|
|
|
|
|
2026-05-12 17:12:09 -07:00
|
|
|
# On agent error/timeout, set var(txn.coraza.error). We DON'T add a
|
|
|
|
|
# corresponding `http-request deny if { var(txn.coraza.error) -m bool }`
|
|
|
|
|
# in the frontend, so the request continues uninspected. This is the
|
|
|
|
|
# fail-open posture: WAF outage shouldn't 503 customer traffic.
|
|
|
|
|
option set-on-error error
|
2026-05-12 16:49:29 -07:00
|
|
|
|
|
|
|
|
timeout hello 2s
|
|
|
|
|
timeout idle 2m
|
|
|
|
|
timeout processing 100ms
|
|
|
|
|
|
|
|
|
|
use-backend coraza-spoa-backend
|
|
|
|
|
log global
|
|
|
|
|
|
2026-05-12 17:12:09 -07:00
|
|
|
# Per-request inspection message. No `event` directive — fires only when
|
|
|
|
|
# explicitly invoked from haproxy.cfg via `http-request send-spoe-group`.
|
|
|
|
|
# Arg order/names are mandatory: Coraza-SPOA parses positionally and renames
|
|
|
|
|
# break the agent. `app=str(haproxy)` is the literal application name from
|
|
|
|
|
# coraza-spoa's config.yaml `applications:` block.
|
2026-05-14 08:52:01 -07:00
|
|
|
#
|
|
|
|
|
# src-ip uses var(txn.real_ip) — HAProxy resolves the real client IP at the
|
|
|
|
|
# top of the frontend (CF-Connecting-IP > X-Real-IP > X-Forwarded-For > src,
|
|
|
|
|
# only honoring those headers from trusted proxies). Falls back to `src`
|
|
|
|
|
# when no proxy headers are present. This is what shows up as `client_ip`
|
|
|
|
|
# in /var/log/coraza/audit.log and the rule manager's view-matches panel.
|
2026-05-12 17:12:09 -07:00
|
|
|
spoe-message coraza-req
|
2026-05-14 08:52:01 -07:00
|
|
|
args app=str(haproxy) src-ip=var(txn.real_ip) src-port=src_port dst-ip=dst dst-port=dst_port method=method path=path query=query version=req.ver headers=req.hdrs body=req.body
|
2026-05-12 17:12:09 -07:00
|
|
|
|
|
|
|
|
# Group binding for send-spoe-group invocation in the frontend. One group,
|
|
|
|
|
# one message; could add more in the future (e.g. coraza-res for response
|
|
|
|
|
# inspection — currently disabled in coraza-spoa's config.yaml).
|
|
|
|
|
spoe-group coraza-req
|
|
|
|
|
messages coraza-req
|