feat(waf): Phase 3 — HAProxy SPOE-Integration — v1.2.68

- haproxy.cfg.tpl: filter spoe + deny_status 403 + spoe-edgeguard-waf
  Backend (nur gerendert wenn WAFEnabled=true)
- haproxy.go: WAFEnabled in View; WafRepo.ListEnabled() prüft ob WAF
  aktiv; SPOE-Config-File (coraza-spoe.cfg) wird bei WAFEnabled
  atomar geschrieben; SPOEConfigPath konfigurierbar
- waf/spoe.go: uri statt path+query (HAProxy url-Sample = volle URI)

SPOE-Config definiert:
  - Agent: edgeguard-waf-agent, var-prefix=waf, timeout processing 50ms
  - Message: src, method, uri=url, ver=req.ver, headers=req.hdrs,
             host=req.hdr(host)
  - Backend: spoe-edgeguard-waf → 127.0.0.1:9000

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Debian
2026-06-02 15:53:07 +02:00
parent bd32bc343a
commit bf16ce6666
4 changed files with 84 additions and 25 deletions

View File

@@ -32,13 +32,12 @@ func (a *SPOEAgent) ListenAndServe(ctx context.Context) error {
// and optionally sets a txn.waf.status variable to trigger a deny ACL.
func (a *SPOEAgent) handle(ctx context.Context, w *encoding.ActionWriter, m *encoding.Message) {
var (
clientIP string
method string
path string
query string
httpVer string
host string
rawHdrs string
clientIP string
method string
uri string // full request URI (path + optional ?query)
httpVer string
host string
rawHdrs string
)
// Iterate over the key-value pairs HAProxy sent with this message.
@@ -53,10 +52,8 @@ func (a *SPOEAgent) handle(ctx context.Context, w *encoding.ActionWriter, m *enc
}
case entry.NameEquals("method"):
method = string(entry.ValueBytes())
case entry.NameEquals("path"):
path = string(entry.ValueBytes())
case entry.NameEquals("query"):
query = string(entry.ValueBytes())
case entry.NameEquals("uri"):
uri = string(entry.ValueBytes())
case entry.NameEquals("ver"):
httpVer = string(entry.ValueBytes())
case entry.NameEquals("host"):
@@ -89,10 +86,8 @@ func (a *SPOEAgent) handle(ctx context.Context, w *encoding.ActionWriter, m *enc
tx.ProcessConnection(clientIP, 0, "", 0)
}
// Build full URI.
uri := path
if query != "" {
uri += "?" + query
if uri == "" {
uri = "/"
}
if httpVer == "" {
httpVer = "HTTP/1.1"