Skip to content

Commit 3f75be1

Browse files
committed
fix: align Palo Alto Networks filter and rule contracts
1 parent 6c3af7e commit 3f75be1

3 files changed

Lines changed: 253 additions & 76 deletions

File tree

‎filters/audits/paloalto.md‎

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Palo Alto Networks normalization and rule review
2+
3+
Fix configuration, counter names/types and side meaning; honor explicit denial and leave submitted work pending.
4+
5+
This draft targets UTMStack `v11`. It contains 1 filter changes
6+
and 0 rule changes for this technology only. Review covered
7+
1 filter configurations and 7 matching shipped rule files.
8+
Unchanged rules are listed in the regression manifest; they are not duplicated in the diff.
9+
10+
## Contract and validation
11+
12+
- Compared exact standard names/types with go-sdk v1.1.31 and the supplied UTMStack dictionaries.
13+
- Checked documented pipeline ordering, rename/move behavior, open vendor log fields,
14+
event-side versus alert-side fields, and surviving fields used by affected rule predicates/history/grouping.
15+
- Strict SDK configuration decoding and actual CEL compilation pass for this scope.
16+
- 4 synthetic normalization cases pass, including SDK Event conversion and any
17+
trigger predicate assertions recorded in the manifest.
18+
- The scoped alerts module tests and `git diff --check` pass with the shared contract runner applied.
19+
20+
The shared alert-contract PR supplies the reusable Go runner for the manifest in
21+
`plugins/alerts/testdata/filter-contracts/paloalto.json`. Apply that support before running `go test ./...` in `plugins/alerts`.
22+
23+
The model starts from synthetic extraction results. It does not run complex grok,
24+
JSON/KV/XML/CSV extraction, time conversion, dynamic plugins, historical OpenSearch
25+
queries, or the closed EventProcessor. Raw vendor logs and resulting alerts must
26+
still be checked in staging before rollout. No customer false-positive reduction
27+
has been measured and no production rollout is included.
28+
29+
30+
31+
## References
32+
33+
- [SDK schema](https://github.com/threatwinds/go-sdk/blob/v1.1.31/plugins/plugins.proto)
34+
- [Filter steps](https://github.com/threatwinds/go-sdk/wiki/Filter-Steps-Reference)
35+
- [Standard event schema](https://github.com/threatwinds/go-sdk/wiki/Standard-Event-Schema)
36+
- [Rule implementation](https://github.com/threatwinds/go-sdk/wiki/Implementing-Rules)
37+
38+
`afterEvents`, empty noncapturing grok names, supported numeric strings, and custom
39+
`log.*` fields are accepted. Existing textual protocol casing and vendor action names
40+
are preserved unless a concrete consumer mismatch requires correction.

‎filters/paloalto/pa_firewall.yml‎

Lines changed: 131 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1543,15 +1543,15 @@ pipeline:
15431543
source: log.cefOrLeefMsgAll
15441544

15451545
- grok:
1546-
patterns:
1547-
- fieldName: log.irrelevant
1548-
pattern: '{{.data}}(panOSContainerNameSpace=)'
1549-
- fieldName: log.panOSContainerNameSpace
1550-
pattern: '{{.data}}({{.word}}=)'
1551-
- fieldName: log.irrelevant
1552-
pattern: '{{.greedy}}'
1553-
source: log.cefOrLeefMsgAll
1554-
1546+
patterns:
1547+
- fieldName: log.irrelevant
1548+
pattern: '{{.data}}(panOSContainerNameSpace=)'
1549+
- fieldName: log.panOSContainerNameSpace
1550+
pattern: '{{.data}}({{.word}}=)'
1551+
- fieldName: log.irrelevant
1552+
pattern: '{{.greedy}}'
1553+
source: log.cefOrLeefMsgAll
1554+
15551555
- grok:
15561556
patterns:
15571557
- fieldName: log.irrelevant
@@ -1743,14 +1743,14 @@ pipeline:
17431743
source: log.cefOrLeefMsgAll
17441744

17451745
- grok:
1746-
patterns:
1747-
- fieldName: log.irrelevant
1748-
pattern: '{{.data}}(panOSDGl1=)'
1749-
- fieldName: log.panOSDGl1
1750-
pattern: '{{.data}}({{.word}}=)'
1751-
- fieldName: log.irrelevant
1752-
pattern: '{{.greedy}}'
1753-
source: log.cefOrLeefMsgAll
1746+
patterns:
1747+
- fieldName: log.irrelevant
1748+
pattern: '{{.data}}(panOSDGl1=)'
1749+
- fieldName: log.panOSDGl1
1750+
pattern: '{{.data}}({{.word}}=)'
1751+
- fieldName: log.irrelevant
1752+
pattern: '{{.greedy}}'
1753+
source: log.cefOrLeefMsgAll
17541754

17551755
- grok:
17561756
patterns:
@@ -6381,7 +6381,7 @@ pipeline:
63816381
# Detect if its a TUNNEL INSPECTION log
63826382
# ..........................................................................#
63836383
- csv:
6384-
from: log.csvMsgAll
6384+
source: log.csvMsgAll
63856385
separator: ","
63866386
headers:
63876387
- log.receive_time
@@ -6472,7 +6472,7 @@ pipeline:
64726472
# Detect if its a SCTP log
64736473
# ..........................................................................#
64746474
- csv:
6475-
from: log.csvMsgAll
6475+
source: log.csvMsgAll
64766476
separator: ","
64776477
headers:
64786478
- log.receive_time
@@ -6545,7 +6545,7 @@ pipeline:
65456545
# Detect if its a CONFIG log
65466546
#......................................................................#
65476547
- csv:
6548-
from: log.csvMsgAll
6548+
source: log.csvMsgAll
65496549
separator: ','
65506550
headers:
65516551
- log.receive_time
@@ -6580,7 +6580,7 @@ pipeline:
65806580
# Detect if its a AUTHENTICATION log
65816581
#......................................................................#
65826582
- csv:
6583-
from: log.csvMsgAll
6583+
source: log.csvMsgAll
65846584
separator: ','
65856585
headers:
65866586
- log.receive_time
@@ -6633,7 +6633,7 @@ pipeline:
66336633
# Detect if its a SYSTEM log
66346634
#......................................................................#
66356635
- csv:
6636-
from: log.csvMsgAll
6636+
source: log.csvMsgAll
66376637
separator: ','
66386638
headers:
66396639
- log.receive_time
@@ -6667,7 +6667,7 @@ pipeline:
66676667
# Detect if its a CORRELATED EVENTS log
66686668
#......................................................................#
66696669
- csv:
6670-
from: log.csvMsgAll
6670+
source: log.csvMsgAll
66716671
separator: ","
66726672
headers:
66736673
- log.receive_time
@@ -6697,7 +6697,7 @@ pipeline:
66976697
# Detect if its a GTP log
66986698
#......................................................................#
66996699
- csv:
6700-
from: log.csvMsgAll
6700+
source: log.csvMsgAll
67016701
separator: ","
67026702
headers:
67036703
- log.receive_time
@@ -6810,22 +6810,22 @@ pipeline:
68106810
- rename:
68116811
from:
68126812
- log.bytessent
6813-
to: target.bytesSent
6813+
to: origin.bytesSent
68146814

68156815
- rename:
68166816
from:
68176817
- log.bytesreceived
6818-
to: target.bytesReceived
6818+
to: origin.bytesReceived
68196819

68206820
- rename:
68216821
from:
68226822
- log.pktssent
6823-
to: target.packagesSent
6823+
to: origin.packagesSent
68246824

68256825
- rename:
68266826
from:
68276827
- log.pktsreceived
6828-
to: target.packagesReceived
6828+
to: origin.packagesReceived
68296829

68306830
- rename:
68316831
from:
@@ -6850,69 +6850,27 @@ pipeline:
68506850
# ................................................#
68516851
# Adding action result
68526852
# ................................................#
6853-
- add:
6854-
function: string
6855-
params:
6856-
key: actionResult
6857-
value: "allow"
6858-
where: '!exists("log.status") && equalsIgnoreCase("action", "allow")'
68596853

6860-
- add:
6861-
function: string
6862-
params:
6863-
key: actionResult
6864-
value: "denied"
6865-
where: '!exists("log.status") && oneOf("action", ["deny", "Deny"])'
68666854

6867-
- add:
6868-
function: string
6869-
params:
6870-
key: actionResult
6871-
value: "blocked"
6872-
where: '!exists("log.status") && oneOf("action", ["drop", "Drop", "reset-client", "reset-server", "reset-both", "block-url", "block-ip", "random-drop", "sinkhole"])'
68736855

6874-
- add:
6875-
function: string
6876-
params:
6877-
key: actionResult
6878-
value: "Succeeded"
6879-
where: '!exists("log.status") && oneOf("log.result", ["Succeeded", "Submitted"])'
68806856

6881-
- add:
6882-
function: string
6883-
params:
6884-
key: actionResult
6885-
value: "failed"
6886-
where: '!exists("log.status") && oneOf("log.result", ["Failed", "Unauthorized"])'
68876857

6888-
- add:
6889-
function: string
6890-
params:
6891-
key: actionResult
6892-
value: "success"
6893-
where: 'equals("log.status", "success")'
68946858

6895-
- add:
6896-
function: string
6897-
params:
6898-
key: actionResult
6899-
value: "failed"
6900-
where: 'equals("log.status", "failure")'
69016859

69026860
# ................................................#
69036861
# Fileds conversions
69046862
# ................................................#
69056863
- cast:
69066864
fields:
6907-
- target.bytessent
6908-
- target.bytesreceived
6865+
- origin.bytesSent
6866+
- origin.bytesReceived
69096867
to: float
69106868

69116869
- cast:
69126870
fields:
6913-
- target.pktssent
6914-
- target.packagesReceived
6915-
to: int64
6871+
- origin.packagesSent
6872+
- origin.packagesReceived
6873+
to: int
69166874

69176875
- cast:
69186876
fields:
@@ -6941,4 +6899,101 @@ pipeline:
69416899
# ..........................................................................#
69426900
- delete:
69436901
fields:
6944-
- log.csvMsgAll
6902+
- log.csvMsgAll
6903+
6904+
# Normalize explicit outcomes; an unknown outcome remains unset.
6905+
- add:
6906+
function: string
6907+
params:
6908+
key: actionResult
6909+
value: denied
6910+
where: regexMatch("action", "(?i)^(deny|drop|drop ICMP|reset[- ]client|reset[- ]server|reset[- ]both|block-url|block-ip|random-drop|sinkhole)$")
6911+
- add:
6912+
function: string
6913+
params:
6914+
key: actionResult
6915+
value: success
6916+
where: '!exists("actionResult") && equalsIgnoreCase("action", "allow")'
6917+
- add:
6918+
function: string
6919+
params:
6920+
key: actionResult
6921+
value: denied
6922+
where: '!exists("actionResult") && equalsIgnoreCase("log.result", "Unauthorized")'
6923+
- add:
6924+
function: string
6925+
params:
6926+
key: actionResult
6927+
value: failure
6928+
where: '!exists("actionResult") && (equalsIgnoreCase("log.result", "Failed") || equalsIgnoreCase("log.status", "failure"))'
6929+
- add:
6930+
function: string
6931+
params:
6932+
key: actionResult
6933+
value: success
6934+
where: '!exists("actionResult") && (equalsIgnoreCase("log.result", "Succeeded") || equalsIgnoreCase("log.status", "success"))'
6935+
6936+
# Keep addresses in IP fields and retain other source values under log.
6937+
- rename:
6938+
from:
6939+
- origin.ip
6940+
to: log.unparsedOriginIp
6941+
where: exists("origin.ip") && (!(inCIDR("origin.ip","0.0.0.0/0") || inCIDR("origin.ip","::/0")) || oneOf("origin.ip",["0.0.0.0","::"]))
6942+
- rename:
6943+
from:
6944+
- target.ip
6945+
to: log.unparsedTargetIp
6946+
where: exists("target.ip") && (!(inCIDR("target.ip","0.0.0.0/0") || inCIDR("target.ip","::/0")) || oneOf("target.ip",["0.0.0.0","::"]))
6947+
- add:
6948+
function: string
6949+
params:
6950+
key: protocol
6951+
value: ICMP
6952+
where: equals("protocol",1)
6953+
- add:
6954+
function: string
6955+
params:
6956+
key: protocol
6957+
value: TCP
6958+
where: equals("protocol",6)
6959+
- add:
6960+
function: string
6961+
params:
6962+
key: protocol
6963+
value: UDP
6964+
where: equals("protocol",17)
6965+
- add:
6966+
function: string
6967+
params:
6968+
key: protocol
6969+
value: GRE
6970+
where: equals("protocol",47)
6971+
- add:
6972+
function: string
6973+
params:
6974+
key: protocol
6975+
value: ESP
6976+
where: equals("protocol",50)
6977+
- add:
6978+
function: string
6979+
params:
6980+
key: protocol
6981+
value: AH
6982+
where: equals("protocol",51)
6983+
- add:
6984+
function: string
6985+
params:
6986+
key: protocol
6987+
value: ICMPV6
6988+
where: equals("protocol",58)
6989+
- add:
6990+
function: string
6991+
params:
6992+
key: protocol
6993+
value: SCTP
6994+
where: equals("protocol",132)
6995+
- rename:
6996+
from:
6997+
- protocol
6998+
to: log.ipProtocolNumber
6999+
where: exists("protocol") && greaterOrEqual("protocol",0)

0 commit comments

Comments
 (0)