|
1 | | -# Cisco Meraki normalization and rule review |
| 1 | +# Cisco Meraki parsing and rule contracts |
2 | 2 |
|
3 | | -Avoid fabricated success for observations/pending VPN; preserve rule input fields and handle retrospective AMP events without invented source IP. |
| 3 | +This source draft targets UTMStack v11 and revises one filter and its seven rules. |
| 4 | +The meeting follow-up is based on SDK v1.1.31, pinned by `plugins/alerts/go.mod`, |
| 5 | +and the official SDK field and filter/rule documentation. It preserves ingress |
| 6 | +`dataSource` and the physical source/destination roles in network events. It does |
| 7 | +not deploy configuration, generate customer telemetry or claim that an alert fired. |
4 | 8 |
|
5 | | -This draft targets UTMStack `v11`. It contains 1 filter changes |
6 | | -and 1 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 | +## Evidence and its limits |
9 | 10 |
|
10 | | -## Contract and validation |
| 11 | +The current carrier investigation found nine distinct records without recognizable |
| 12 | +Meraki envelopes under `firewall-meraki`: five ISO syslog records from unrelated |
| 13 | +programs and four other unrecognized network/syslog records. They lack normalized Meraki fields. The deployed |
| 14 | +filter SHA-256 is |
| 15 | +`b39216313c9e141d7bb9aef93aafc97f044e482ea7a013bc62ea4bb4ecf64e18`. |
| 16 | +Bounded searches over the retained 30-day window found no strong documented |
| 17 | +Meraki class signatures. That search is not an exhaustive proof that Meraki |
| 18 | +telemetry never arrived. The routing mismatch is a separate ingress-classification issue with its upstream |
| 19 | +producer unresolved; |
| 20 | +this patch does not reinterpret unrelated syslog as Meraki data. |
11 | 21 |
|
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 | | -- 6 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. |
| 22 | +Private raw records, document IDs and instance provenance remain outside the |
| 23 | +repository. All public positive fixtures are fabricated from official Cisco |
| 24 | +examples, not customer records. Positive parsing and detection results below are |
| 25 | +therefore documented-format compatibility checks, not measured recovery of |
| 26 | +customer Meraki events. The reviewed prior source draft is |
| 27 | +`db4ae93a194009ca05631245a6316b6c87134f2c`. |
19 | 28 |
|
20 | | -The shared alert-contract PR supplies the reusable Go runner for the manifest in |
21 | | -`plugins/alerts/testdata/filter-contracts/cisco-meraki.json`. Apply that support before running `go test ./...` in `plugins/alerts`. |
| 29 | +## Producer corrections |
22 | 30 |
|
23 | | -The changed rules also require the shared alert-grouping fix to resolve `lastEvent.*` values correctly at runtime. |
| 31 | +The old raw header paths require a Cisco calendar-time wrapper. The documented |
| 32 | +Meraki native envelope instead starts with fractional epoch, device name and |
| 33 | +an event group. The new anchored paths accept that envelope, a bounded RFC3164 |
| 34 | +wrapper, and the documented standalone Air Marshal form. Group boundaries are |
| 35 | +explicit: device or message text cannot become part of a native event category. |
| 36 | +The old greedy group copy was not overwriting an existing subtype; it was the |
| 37 | +sole producer of `log.eventType`. |
24 | 38 |
|
25 | | -The model starts from synthetic extraction results. It does not run complex grok, |
26 | | -JSON/KV/XML/CSV extraction, time conversion, dynamic plugins, historical OpenSearch |
27 | | -queries, or the closed EventProcessor. Raw vendor logs and resulting alerts must |
28 | | -still be checked in staging before rollout. No customer false-positive reduction |
29 | | -has been measured and no production rollout is included. |
| 39 | +`log.merakiGroup` retains the outer event group and `log.merakiType` retains the |
| 40 | +header device name. `log.eventType` exposes the canonical category; nested Air |
| 41 | +Marshal messages use `airmarshal_events`. `log.type` holds the events/Air Marshal |
| 42 | +classification, while `log.alertType` holds the security-event class. These fields |
| 43 | +now match the rule consumers. Class-prefix recognizers are anchored, and quoted |
| 44 | +field recovery cannot treat message text as an independent identity or decision. |
| 45 | +The full body remains available as `log.message`. |
30 | 46 |
|
31 | | -Current Meraki security events retain their group/message for the AMP consumer. Retrospective malicious dispositions do not report a source IP, so the rule does not invent or require one; grouping includes dataSource. Source: https://documentation.meraki.com/General_Administration/Monitoring_and_Reporting/Syslog_Event_Types_and_Log_Samples |
| 47 | +Legacy body handlers remain for event families outside the bounded new handlers; |
| 48 | +legacy header/control-field rewrites cannot overwrite a recognized native header. |
| 49 | +Representative DHCP, VPN connectivity, cellular status, STP, disassociation and |
| 50 | +URL formats have regression fixtures. Not every historical vendor variant has |
| 51 | +been exercised, and the model's built-in legacy regex aliases are approximations |
| 52 | +of the closed executor's patterns. New native patterns are explicit in YAML. |
| 53 | + |
| 54 | +Three review controls reproduced false fields before correction: a quoted VPN |
| 55 | +fragment produced a peer IP and success, quoted disassociation field names |
| 56 | +produced success, and an embedded legacy date header reclassified application |
| 57 | +text as a flow. Native VPN/disassociation now consume only their top-level |
| 58 | +tokens, and both legacy header patterns require the start of the raw record. |
| 59 | +Genuine VPN connectivity fields, full disassociation metadata and both leading |
| 60 | +legacy header forms have positive controls. Disassociation timing/radio fields |
| 61 | +remain metadata; their presence alone does not establish authentication success. |
| 62 | + |
| 63 | +| Vendor information | Result | |
| 64 | +|---|---| |
| 65 | +| Source/destination addresses | Captured and cleaned under vendor fields, validated at promotion, then written to `origin.ip`/`target.ip`. Invalid/unspecified values stay under `log.sourceIp`/`log.destinationIp`; original native `log.src`/`log.dst` also remain. | |
| 66 | +| IPv6 and endpoint ports | Valid IPv6 ending in `::` is not truncated by colon cleanup. Semantic zero CIDRs cover alternate and IPv4-mapped unspecified forms. Ports retain numeric bounds before SDK conversion. | |
| 67 | +| Flow/firewall decision | Documented `flows`, `firewall`, `cellular_firewall`, `vpn_firewall` and `l7_firewall` groups are recognized. Explicit allow/deny/block becomes success/denied as a policy outcome, not proof a connection completed. | |
| 68 | +| IDS / AMP enforcement | IDS `decision=blocked` and AMP scan `action=block` produce denied. Mere IDS observation and retrospective AMP `action=allow` do not manufacture execution success. | |
| 69 | +| AnyConnect authentication | Only the documented auth-success/failure classes extract `Peer IP` from their structured message. Generic VPN negotiation or text mentioning failure does not become authentication evidence. | |
| 70 | +| AMP hash and URL | Valid 64-hex `log.sha256` is copied to `target.sha256`, describing the file offered by the remote download endpoint; vendor hash is retained. A full URL maps to `target.url`. Threat names such as EICAR classifications are not filenames. | |
| 71 | +| 802.1X identity | Documented identity maps to `origin.user`; physical switch interface numbers stay in `log.switchPort`, not transport `origin.port`. | |
| 72 | +| Wireless device | Packet-flood device and Air Marshal source/destination MACs retain their documented roles. The observing appliance name is not an attacker hostname. | |
| 73 | +| IDS `dhost` | Retained as `log.dhost`; it is no longer unconditionally assigned to the source MAC. Its all-direction endpoint semantics are not established by the available examples. | |
| 74 | +| Auxiliary geolocation | Hostnames and zero addresses never enter geolocation. Results use distinct `log.serverGeolocation` / `log.localGeolocation` fields rather than children of scalar address fields. `ip_resp` is response timing and is not geolocated. | |
| 75 | + |
| 76 | +The SDK uses string fields for outcomes and protocol. This change preserves the |
| 77 | +existing protocol conversion policy and uses explicit outcome evidence. Fractional |
| 78 | +epoch values remain vendor time metadata; a verified conversion into `deviceTime` |
| 79 | +was not established here. Auxiliary geolocation field names and new consumer |
| 80 | +aliases require review of saved queries during staging; private dashboards were |
| 81 | +not enumerated. |
| 82 | + |
| 83 | +## Consumers and identities |
| 84 | + |
| 85 | +- AMP consumes exact documented scan/disposition-change classes and malicious |
| 86 | + disposition. Network source remains the downloading client; the rule's |
| 87 | + adversary side is the remote target serving the file. This is not proof that |
| 88 | + the client executed malware. Retrospective events remain eligible without IPs. |
| 89 | +- AMP groups valid hashes using a `hash` namespace. Missing or malformed hashes |
| 90 | + retain the vendor value and use the actual ingress `Event.id` in an `event` |
| 91 | + namespace, keeping distinct records separate. The filter does not create an |
| 92 | + event ID; the input producer supplies it. Neither a usable hash nor an ingress |
| 93 | + ID is an explicit completeness negative, not a fabricated file identity. |
| 94 | +- IDS accepts high/medium priorities 1 and 2, including documented legacy |
| 95 | + `ids-alerts` records containing only a source endpoint. A target IP is not |
| 96 | + invented to satisfy a rule. |
| 97 | +- Rogue SSID and Air Marshal rules consume the actual Air Marshal class. The |
| 98 | + Evil Twin rule requires `ssid_spoofing_detected`, not a generic rogue SSID. |
| 99 | + The two rogue rules retain overlapping coverage and the existing RSSI threshold |
| 100 | + for team review; primary syslog RSSI units were not established. Cisco documents |
| 101 | + removal of these legacy rogue/spoofing messages in MR29 and later. |
| 102 | +- Wireless intrusion consumes `device_packet_flood` with `state=start`; an end |
| 103 | + event or ordinary message containing attack words is not a new attack trigger. |
| 104 | +- VPN uses exact AnyConnect auth failure, valid produced origin IP, and meaningful |
| 105 | + ingress/device identities. Its 10-in-15-minute history counts only the filter's |
| 106 | + matching failure marker for that source, collector and device. Generic traffic |
| 107 | + from the same IP no longer satisfies the history. Input markers are cleared. |
| 108 | + |
| 109 | +History windows use the SDK's processing-time lower bound on `@timestamp`, not |
| 110 | +strict event-time sequencing. Older indexed records have no new candidate marker; |
| 111 | +allow the 15-minute history window to warm up when staging the filter and rules |
| 112 | +together. Indexed `lastEvent.*` grouping requires the separate alert-foundation |
| 113 | +fix; this source draft does not duplicate it. |
| 114 | + |
| 115 | +## Verification |
| 116 | + |
| 117 | +`go test ./... -count=1 -v` passes in `plugins/alerts` with the optional private |
| 118 | +routing evidence enabled. `git diff --check` also passes. |
| 119 | + |
| 120 | +- 85 fabricated raw cases exercise all seven rule predicates, native envelopes, |
| 121 | + quoted field/class injection, valid and unspecified addresses, documented |
| 122 | + legacy event families, decision semantics, hash/ID fallback and new mappings. |
| 123 | +- Fourteen isolated auxiliary-geolocation controls test both address fields with |
| 124 | + valid IPs, hostnames and alternate unspecified representations. These are |
| 125 | + source-step controls, not legacy-envelope parsing proofs. |
| 126 | +- Actual SDK CEL and Event/Alert serialization validate consumer identities, |
| 127 | + physical endpoint preservation, AMP actor direction and grouping separation. |
| 128 | +- Actual SDK history executes against a loopback HTTP mock for the VPN threshold, |
| 129 | + count-minus-one/count, inside/expired windows, source/device/collector isolation, |
| 130 | + benign raw classes and missing placeholders. It does not query a customer. |
| 131 | +- All nine private unrelated/unrecognized records pass as negative routing controls without |
| 132 | + invented Meraki identities, outcomes or candidates. |
| 133 | +- The shared manifest contains three explicitly isolated normalization/empty |
| 134 | + identity controls. It does not prove raw parsing; the standalone raw suite does |
| 135 | + that within its stated model boundary. |
| 136 | +- The final shared-runner overlay passes 121 test/subtest records, with the |
| 137 | + optional private replay skipped there and run separately with its evidence. |
| 138 | + |
| 139 | +The closed EventProcessor, live OpenSearch, dynamic geolocation lookup and alert |
| 140 | +publication are not run by this harness. No production false-positive reduction |
| 141 | +has been measured. Before production approval, stage actual native Meraki payloads |
| 142 | +through the collector/engine, inspect produced alerts and grouping, check parsing |
| 143 | +cost at realistic event rates, and investigate the separate carrier-routing issue. |
32 | 144 |
|
33 | 145 | ## References |
34 | 146 |
|
35 | | -- [SDK schema](https://github.com/threatwinds/go-sdk/blob/v1.1.31/plugins/plugins.proto) |
| 147 | +- [Official Meraki syslog formats and examples](https://documentation.meraki.com/Platform_Management/Dashboard_Administration/Operate_and_Maintain/Monitoring_and_Reporting/Syslog_Event_Types_and_Log_Samples) |
| 148 | +- [SDK v1.1.31 schema](https://github.com/threatwinds/go-sdk/blob/v1.1.31/plugins/plugins.proto) |
| 149 | +- [Standard event semantics](https://github.com/threatwinds/go-sdk/wiki/Standard-Event-Schema) |
36 | 150 | - [Filter steps](https://github.com/threatwinds/go-sdk/wiki/Filter-Steps-Reference) |
37 | | -- [Standard event schema](https://github.com/threatwinds/go-sdk/wiki/Standard-Event-Schema) |
38 | 151 | - [Rule implementation](https://github.com/threatwinds/go-sdk/wiki/Implementing-Rules) |
39 | | - |
40 | | -`afterEvents`, empty noncapturing grok names, supported numeric strings, and custom |
41 | | -`log.*` fields are accepted. Existing textual protocol casing and vendor action names |
42 | | -are preserved unless a concrete consumer mismatch requires correction. |
|
0 commit comments