feat(waf): log why Coraza acted (wrule/wrules/wscore); VERSION 2026.10.4
HAProxy Manager Build and Push / Build-and-Push (push) Successful in 3m14s
HAProxy Manager Build and Push / Build-and-Push (push) Successful in 3m14s
coraza-spoa v0.7.1 already returns the interrupting rule id (txn.coraza.ruleid) and, when the request message sends exportRuleIDs=bool(true), the comma list of every matched CRS attack rule (txn.coraza.rule_ids) plus the inbound anomaly score. Send the arg and append all three to the access log so a block's cause (e.g. 920440,949110 score 5) is visible in haproxy.log without opening the Coraza audit log. Fields are appended last; existing ones unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
519f2d8ade
commit
cbbd15b787
4 files changed
+33
-4
No files matched your search
@@ -160,7 +160,16 @@ class ListenerWithCoraza(unittest.TestCase):
|
||||
def test_access_log_carries_coverage_fields(self):
|
||||
lf = [l for l in self.lines if l.startswith('log-format ')]
|
||||
self.assertEqual(len(lf), 1)
|
||||
self.assertTrue(lf[0].endswith('wafb=%[var(txn.waf_body)] wafe=%[var(txn.coraza.error)]"'))
|
||||
self.assertIn('wafb=%[var(txn.waf_body)] wafe=%[var(txn.coraza.error)]', lf[0])
|
||||
|
||||
def test_access_log_carries_waf_verdict_fields(self):
|
||||
"""wrule/wrules/wscore are appended LAST so any consumer anchored on
|
||||
the earlier fields keeps working."""
|
||||
lf = [l for l in self.lines if l.startswith('log-format ')]
|
||||
self.assertEqual(len(lf), 1)
|
||||
self.assertTrue(lf[0].endswith(
|
||||
'wrule=%[var(txn.coraza.ruleid)] wrules=%[var(txn.coraza.rule_ids)] '
|
||||
'wscore=%[var(txn.coraza.anomaly_score)]"'))
|
||||
|
||||
def test_fail_open_preserved(self):
|
||||
"""Nothing may deny on var(txn.coraza.error): an SPOA outage must not
|
||||
@@ -247,6 +256,11 @@ class CorazaTransactionIdIsTheRequestReference(unittest.TestCase):
|
||||
self.assertIn('coraza-req', self.messages)
|
||||
self.assertEqual(self.args_of('coraza-req').get('id'), 'unique-id')
|
||||
|
||||
def test_request_message_exports_rule_ids(self):
|
||||
"""Without exportRuleIDs coraza-spoa never sets txn.coraza.rule_ids
|
||||
and the access log's wrules= is always '-'."""
|
||||
self.assertEqual(self.args_of('coraza-req').get('exportRuleIDs'), 'bool(true)')
|
||||
|
||||
def test_app_is_still_the_first_arg(self):
|
||||
"""agent.go HandleSPOE Panics unless the FIRST kv entry is `app`."""
|
||||
for name, args in self.messages.items():
|
||||
|
||||
Reference in new issue
Block a user