mirror of
https://github.com/domainaware/parsedmarc.git
synced 2026-08-18 05:03:19 +00:00
Store CBN parser booleans as typed bool_value
The alignment flags and normalized_timespan were stored as
string_value "true"/"false" in additional.fields, which diverged from
the [gsecops] API output (a protobuf Struct, where they are real
booleans) — a UDM search written for one delivery path would not match
the other for those four fields.
Google's parser extension examples document the boolean idiom this
uses: build a string, convert to boolean, rename into the boolean
field. It is the boolean analogue of the number_value chain already
used for count/source_asn (proven in the content-hub Azure Cosmos DB
parser), and the UDM search docs confirm additional fields are
matchable via value.bool_value. The string conversion in step 1b
remains, because CBN conditionals compare against the preserved JSON
type and the == "true"/"false" guards need strings.
With this, both delivery paths emit identical value types for every
additional.fields key. The prior justification ("content-hub never
uses bool_value") described the absence of precedent, not a
prohibition; the documented boolean example is the stronger authority.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
fba083f351
commit
c8e8cb54c0
@@ -71,11 +71,16 @@ DMARC types.
|
||||
2. **JSON types** — Chronicle's `json{}` filter **preserves the original JSON
|
||||
type**, so parsedmarc's booleans and numbers are handled differently:
|
||||
- **Booleans** (`dmarc_aligned` / `spf_aligned` / `dkim_aligned` /
|
||||
`normalized_timespan`) are converted to strings so `[dmarc_aligned] ==
|
||||
"false"` works, and stored as `string_value` (Google's content-hub parsers
|
||||
never use `bool_value`). Note that `testing` is **not** a boolean —
|
||||
parsedmarc emits the RFC 9990 `t=` flag as the string `"y"`/`"n"` — so it
|
||||
is passed through as a string and guarded with `!= ""`.
|
||||
`normalized_timespan`) are converted to strings because CBN conditionals
|
||||
compare against the preserved type, so `[dmarc_aligned] == "false"` needs
|
||||
a string. In `additional.fields` they are stored as typed **`bool_value`**
|
||||
— built as a string, `convert`-ed back to `boolean`, then renamed — the
|
||||
boolean pattern from Google's
|
||||
[parser extension examples](https://docs.cloud.google.com/chronicle/docs/event-processing/parser-extension-examples);
|
||||
UDM search matches them with `value.bool_value`. Note that `testing` is
|
||||
**not** a boolean — parsedmarc emits the RFC 9990 `t=` flag as the string
|
||||
`"y"`/`"n"` — so it is passed through as a string and guarded with
|
||||
`!= ""`.
|
||||
- **Numbers** (`count` / `*_session_count` / `source_asn`) are stored as
|
||||
`number_value` — built as a string, `convert`-ed to `uinteger`, then
|
||||
renamed — so SecOps can range-query and sort them (parsedmarc's "store
|
||||
@@ -83,6 +88,9 @@ DMARC types.
|
||||
so a tenant where `%{}` rejects non-string fields degrades to a missing
|
||||
`additional.fields` entry instead of `_failed_parsing_`.
|
||||
|
||||
Both value types match what the `[gsecops]` API output emits, so UDM
|
||||
searches and dashboards port between the two delivery paths unchanged.
|
||||
|
||||
Every `if`-tested field is initialized to `""` *before* `json` and guarded
|
||||
with `!= ""`: CBN raises `_failed_parsing_` on a conditional referencing an
|
||||
absent field, and treats an initialized-but-empty field as present. A
|
||||
@@ -205,7 +213,8 @@ Suggested order:
|
||||
depends on.
|
||||
2. The two aggregates — confirm the `dmarc_aligned=false` one yields
|
||||
`security_result.category = AUTH_VIOLATION`, that `count` and `source_asn`
|
||||
land as `number_value`, and that the boolean→string handling holds.
|
||||
land as `number_value`, and that the alignment booleans land as
|
||||
`bool_value` (queryable as `additional.fields["dmarc_aligned"].value.bool_value`).
|
||||
3. The SMTP TLS rows — confirm the success row produces a `GENERIC_EVENT` with
|
||||
`target.hostname` and no `security_result`, and the failure rows produce
|
||||
`security_result.action = FAIL`.
|
||||
|
||||
Reference in New Issue
Block a user