diff --git a/filters/audits/cisco-switch.md b/filters/audits/cisco-switch.md new file mode 100644 index 000000000..89a1ea610 --- /dev/null +++ b/filters/audits/cisco-switch.md @@ -0,0 +1,40 @@ +# Cisco Switch normalization and rule review + +Normalize authentication/ARP outcomes and the syslog severity scale. + +This draft targets UTMStack `v11`. It contains 1 filter changes +and 0 rule changes for this technology only. Review covered +1 filter configurations and 3 matching shipped rule files. +Unchanged rules are listed in the regression manifest; they are not duplicated in the diff. + +## Contract and validation + +- Compared exact standard names/types with go-sdk v1.1.31 and the supplied UTMStack dictionaries. +- Checked documented pipeline ordering, rename/move behavior, open vendor log fields, + event-side versus alert-side fields, and surviving fields used by affected rule predicates/history/grouping. +- Strict SDK configuration decoding and actual CEL compilation pass for this scope. +- 5 synthetic normalization cases pass, including SDK Event conversion and any + trigger predicate assertions recorded in the manifest. +- The scoped alerts module tests and `git diff --check` pass with the shared contract runner applied. + +The shared alert-contract PR supplies the reusable Go runner for the manifest in +`plugins/alerts/testdata/filter-contracts/cisco-switch.json`. Apply that support before running `go test ./...` in `plugins/alerts`. + +The model starts from synthetic extraction results. It does not run complex grok, +JSON/KV/XML/CSV extraction, time conversion, dynamic plugins, historical OpenSearch +queries, or the closed EventProcessor. Raw vendor logs and resulting alerts must +still be checked in staging before rollout. No customer false-positive reduction +has been measured and no production rollout is included. + + + +## References + +- [SDK schema](https://github.com/threatwinds/go-sdk/blob/v1.1.31/plugins/plugins.proto) +- [Filter steps](https://github.com/threatwinds/go-sdk/wiki/Filter-Steps-Reference) +- [Standard event schema](https://github.com/threatwinds/go-sdk/wiki/Standard-Event-Schema) +- [Rule implementation](https://github.com/threatwinds/go-sdk/wiki/Implementing-Rules) + +`afterEvents`, empty noncapturing grok names, supported numeric strings, and custom +`log.*` fields are accepted. Existing textual protocol casing and vendor action names +are preserved unless a concrete consumer mismatch requires correction. diff --git a/filters/cisco/cs_switch.yml b/filters/cisco/cs_switch.yml index bb06b6def..25258a177 100644 --- a/filters/cisco/cs_switch.yml +++ b/filters/cisco/cs_switch.yml @@ -174,7 +174,7 @@ pipeline: function: string params: key: actionResult - value: failed + value: failure where: equals("log.facility", "DOT1X") && equals("log.facilityMnemonic", "FAIL") - add: @@ -188,34 +188,48 @@ pipeline: function: string params: key: actionResult - value: blocked + value: denied where: equals("log.facility", "SW_DAI") && oneOf("log.facilityMnemonic", ["DHCP_SNOOPING_DENY", "INVALID_ARP", "ACL_DENY"]) #......................................................................# # Decoding severity + #......................................................................# + # Removing unused fields + - delete: + fields: + - log.switchHeader + - log.irrelevant + - log.tmpFacilityMnemonic + - log.aclName + - log.aclAction + + # Normalize the source event severity. - add: - function: 'string' + function: string params: key: severity - value: 'high' - where: oneOf("log.severity", ["0", "1", "2", "3"]) + value: critical + where: oneOf("log.severity", [0,1,2]) - add: - function: 'string' + function: string params: key: severity - value: 'medium' - where: log.severity=="4" + value: error + where: oneOf("log.severity", [3]) - add: - function: 'string' + function: string params: key: severity - value: 'low' - where: oneOf("log.severity", ["5", "6", "7"]) - #......................................................................# - # Removing unused fields - - delete: - fields: - - log.switchHeader - - log.irrelevant - - log.tmpFacilityMnemonic - - log.aclName - - log.aclAction \ No newline at end of file + value: warning + where: oneOf("log.severity", [4]) + - add: + function: string + params: + key: severity + value: info + where: oneOf("log.severity", [5,6]) + - add: + function: string + params: + key: severity + value: debug + where: oneOf("log.severity", [7]) diff --git a/plugins/alerts/testdata/filter-contracts/cisco-switch.json b/plugins/alerts/testdata/filter-contracts/cisco-switch.json new file mode 100644 index 000000000..7d7d23e8a --- /dev/null +++ b/plugins/alerts/testdata/filter-contracts/cisco-switch.json @@ -0,0 +1,98 @@ +{ + "technology": "Cisco Switch", + "filters": [ + "filters/cisco/cs_switch.yml" + ], + "rules": [ + "rules/cisco/cs_switch/arp_poisoning_detection.yml", + "rules/cisco/cs_switch/mac_address_spoofing.yml", + "rules/cisco/cs_switch/vlan_hopping_attempts.yml" + ], + "fixtures": [ + { + "name": "cisco_switch_severity_0", + "filter": "cisco/cs_switch.yml", + "input": { + "log": { + "severity": "0", + "facility": "DOT1X", + "facilityMnemonic": "FAIL" + } + }, + "expected": { + "severity": "critical", + "actionResult": "failure" + }, + "absent": [], + "rules": {} + }, + { + "name": "cisco_switch_severity_3", + "filter": "cisco/cs_switch.yml", + "input": { + "log": { + "severity": "3", + "facility": "DOT1X", + "facilityMnemonic": "FAIL" + } + }, + "expected": { + "severity": "error", + "actionResult": "failure" + }, + "absent": [], + "rules": {} + }, + { + "name": "cisco_switch_severity_4", + "filter": "cisco/cs_switch.yml", + "input": { + "log": { + "severity": "4", + "facility": "DOT1X", + "facilityMnemonic": "FAIL" + } + }, + "expected": { + "severity": "warning", + "actionResult": "failure" + }, + "absent": [], + "rules": {} + }, + { + "name": "cisco_switch_severity_6", + "filter": "cisco/cs_switch.yml", + "input": { + "log": { + "severity": "6", + "facility": "DOT1X", + "facilityMnemonic": "FAIL" + } + }, + "expected": { + "severity": "info", + "actionResult": "failure" + }, + "absent": [], + "rules": {} + }, + { + "name": "cisco_switch_severity_7", + "filter": "cisco/cs_switch.yml", + "input": { + "log": { + "severity": "7", + "facility": "DOT1X", + "facilityMnemonic": "FAIL" + } + }, + "expected": { + "severity": "debug", + "actionResult": "failure" + }, + "absent": [], + "rules": {} + } + ] +}