Store numbers as number_value; fix conditional guards to != ""

Two corrections confirmed against Google's official content-hub parsers
(content/parsers/third_party/community/*/cbn):

1. Numbers as numbers. count, source_asn, successful_session_count and
   failed_session_count were being stored in additional.fields as string_value.
   Store them as number_value instead (build string -> convert to uinteger ->
   rename to number_value, the content-hub idiom), so SecOps can range-query and
   sort them, per parsedmarc's "store numbers as numbers" rule. Booleans stay
   string_value (content-hub never uses bool_value) and are still converted in
   step 1b for the == "true"/"false" comparisons.

2. Conditional guards. Replaced bare `if [field] {` with `if [field] != "" {`
   (76 guards + the detection cascade + policy_override). After 1a initializes
   every tested field to "", a bare `if` is true for an empty field (Logstash/CBN
   semantics), which would misfire detection and emit empty labels. content-hub
   uses `!= ""` ~111x vs 2 bare (both flags); parser flags (no_json_payload,
   not_json, *_nan) correctly stay bare.

Verified: braces balance, no stray bare field-guards, all if-tested fields
initialized, all four numeric fields emit number_value.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sean Whalen
2026-06-04 12:08:10 -04:00
parent 05c9177d73
commit aabcfb4298
2 changed files with 151 additions and 121 deletions
+17 -11
View File
@@ -48,17 +48,23 @@ DMARC types.
## Caveats
1. **Unvalidated** — see [Status](#status).
2. **JSON type handling** — parsedmarc emits `dmarc_aligned` / `spf_aligned` /
`dkim_aligned` / `testing` / `normalized_timespan` as JSON booleans and
`count` / `*_session_count` / `source_asn` as numbers. Chronicle's `json{}`
filter **preserves the original JSON type**, so the parser explicitly
converts these to strings (`mutate { convert => { … => "string" } }`) before
any comparison — otherwise `[dmarc_aligned] == "false"` would never match.
Relatedly, every field tested in an `if` is initialized to `""` *before* the
`json` filter, because CBN raises `_failed_parsing_` on a conditional that
references a field absent from the log. A DMARC-fail record
(`dmarc_aligned=false`) should yield `security_result.category =
AUTH_VIOLATION` — still worth confirming in the validation tool.
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` / `testing`
/ `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`).
- **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
numbers as numbers" rule).
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
DMARC-fail record (`dmarc_aligned=false`) should yield
`security_result.category = AUTH_VIOLATION` — worth confirming in the
validation tool.
3. **Aggregate count** — a DMARC aggregate record summarizes `count` messages
from one source IP, not a single message. Each record becomes one
`EMAIL_TRANSACTION` with `count` carried in `additional.fields`. There is no
+134 -110
View File
@@ -50,11 +50,16 @@ filter {
# run through the SecOps parser-validation tool against a live tenant.
# Validate with the sample events in README.md before production use.
# 2. JSON TYPES ARE PRESERVED. The CBN json{} filter keeps the original JSON
# type (a JSON boolean stays a boolean, a number stays a number), so
# parsedmarc's boolean *_aligned / testing / normalized_timespan and
# numeric count / *_count would NOT match string comparisons. This parser
# converts them to strings (step 1b) before any `== "true"` / `== "false"`
# test or %{...} use -- as Google's official content-hub parsers do.
# type (a JSON boolean stays a boolean, a number stays a number).
# Booleans (*_aligned / testing / normalized_timespan) are converted to
# strings (step 1b) so `== "true"` / `== "false"` tests work, and stored
# as string_value (content-hub never uses bool_value). Numbers (count /
# *_session_count / source_asn) are stored as number_value -- built as a
# string, convert-ed to uinteger, then renamed to number_value -- so
# SecOps can range-query and sort them. Matches the content-hub parsers.
# 2b. CONDITIONALS. Every field tested in an `if` is initialized to "" in
# step 1a, and guards use `if [field] != ""` (not bare `if [field]`,
# which is true for an initialized-but-empty field). Matches content-hub.
# 3. AGGREGATE COUNT. A DMARC aggregate record summarizes "count" messages
# from one source IP, not a single message. Each becomes one
# EMAIL_TRANSACTION with "count" carried in additional.fields; there is no
@@ -184,11 +189,14 @@ filter {
}
# ---------------------------------------------------------------------------
# 1b. Convert parsedmarc's JSON booleans/numbers to strings. The json{} filter
# PRESERVES the original JSON type, so without this, [dmarc_aligned] is a
# boolean and `== "false"` never matches (and %{count} on an int is
# unreliable). Fields left as "" by step 1a convert as a harmless no-op.
# Google's official content-hub parsers use mutate{convert} the same way.
# 1b. Convert parsedmarc's JSON booleans to strings so they can be compared.
# The json{} filter PRESERVES the original JSON type, so without this
# [dmarc_aligned] is a boolean and `== "false"` never matches. Booleans are
# stored as string_value (matching Google's content-hub parsers, which
# never use bool_value). Numeric fields are deliberately NOT converted
# here -- they are stored as number_value (not string) in additional.fields
# so SecOps can range-query and sort them; see the count / *_session_count
# / source_asn blocks below.
# ---------------------------------------------------------------------------
mutate {
convert => {
@@ -197,10 +205,6 @@ filter {
"dkim_aligned" => "string"
"testing" => "string"
"normalized_timespan" => "string"
"count" => "string"
"source_asn" => "string"
"successful_session_count" => "string"
"failed_session_count" => "string"
}
on_error => "convert_error"
}
@@ -218,11 +222,11 @@ filter {
# (a generic name), and dmarc_aligned (a boolean that only becomes testable
# after the convert in step 1b -- detection should not depend on that).
# ---------------------------------------------------------------------------
if [feedback_type] {
if [feedback_type] != "" {
mutate { replace => { "report_type" => "failure" } }
} else if [policy_type] {
} else if [policy_type] != "" {
mutate { replace => { "report_type" => "smtp_tls" } }
} else if [xml_schema] {
} else if [xml_schema] != "" {
mutate { replace => { "report_type" => "aggregate" } }
}
@@ -238,7 +242,7 @@ filter {
mutate { replace => { "event_type" => "EMAIL_TRANSACTION" } }
if [report_id] {
if [report_id] != "" {
mutate {
replace => {
"event.idm.read_only_udm.metadata.product_log_id" => "%{report_id}"
@@ -247,7 +251,7 @@ filter {
}
# -- event timestamp: start of the record's reporting interval (UTC). --
if [begin_date] {
if [begin_date] != "" {
date {
match => ["begin_date", "yyyy-MM-dd HH:mm:ss"]
timezone => "UTC"
@@ -256,20 +260,20 @@ filter {
}
# -- principal: the sending source (machine details only). --
if [source_ip_address] {
if [source_ip_address] != "" {
mutate {
merge => { "event.idm.read_only_udm.principal.ip" => "source_ip_address" }
on_error => "agg_src_ip_error"
}
}
if [source_reverse_dns] {
if [source_reverse_dns] != "" {
mutate {
replace => {
"event.idm.read_only_udm.principal.hostname" => "%{source_reverse_dns}"
}
}
}
if [source_country] {
if [source_country] != "" {
mutate {
replace => {
"event.idm.read_only_udm.principal.location.country_or_region" => "%{source_country}"
@@ -278,7 +282,7 @@ filter {
}
# -- target: the domain the report is about. --
if [domain] {
if [domain] != "" {
mutate {
replace => {
"event.idm.read_only_udm.target.hostname" => "%{domain}"
@@ -287,7 +291,7 @@ filter {
}
# -- email: aggregate only carries the From domain (see caveat 4). --
if [header_from] {
if [header_from] != "" {
mutate {
replace => {
"event.idm.read_only_udm.network.email.from" => "%{header_from}"
@@ -325,73 +329,78 @@ filter {
}
# -- additional.fields: DMARC dimensions a dashboard would filter on. --
if [org_name] {
if [org_name] != "" {
mutate {
replace => { "f_org_name.key" => "org_name" "f_org_name.value.string_value" => "%{org_name}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_org_name" }
}
}
if [org_email] {
if [org_email] != "" {
mutate {
replace => { "f_org_email.key" => "org_email" "f_org_email.value.string_value" => "%{org_email}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_org_email" }
}
}
if [begin_date] {
if [begin_date] != "" {
mutate {
replace => { "f_begin.key" => "begin_date" "f_begin.value.string_value" => "%{begin_date}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_begin" }
}
}
if [end_date] {
if [end_date] != "" {
mutate {
replace => { "f_end.key" => "end_date" "f_end.value.string_value" => "%{end_date}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_end" }
}
}
if [count] {
mutate {
replace => { "f_count.key" => "count" "f_count.value.string_value" => "%{count}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_count" }
}
mutate {
replace => { "f_count.key" => "count" "f_count.value.string_value" => "%{count}" }
}
if [p] {
mutate {
convert => { "f_count.value.string_value" => "uinteger" }
on_error => "count_nan"
}
if ![count_nan] {
mutate { rename => { "f_count.value.string_value" => "f_count.value.number_value" } }
mutate { merge => { "event.idm.read_only_udm.additional.fields" => "f_count" } }
}
if [p] != "" {
mutate {
replace => { "f_p.key" => "dmarc_policy" "f_p.value.string_value" => "%{p}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_p" }
}
}
if [sp] {
if [sp] != "" {
mutate {
replace => { "f_sp.key" => "dmarc_subdomain_policy" "f_sp.value.string_value" => "%{sp}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_sp" }
}
}
if [np] {
if [np] != "" {
mutate {
replace => { "f_np.key" => "dmarc_np_policy" "f_np.value.string_value" => "%{np}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_np" }
}
}
if [pct] {
if [pct] != "" {
mutate {
replace => { "f_pct.key" => "dmarc_pct" "f_pct.value.string_value" => "%{pct}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_pct" }
}
}
if [fo] {
if [fo] != "" {
mutate {
replace => { "f_fo.key" => "dmarc_fo" "f_fo.value.string_value" => "%{fo}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_fo" }
}
}
if [adkim] {
if [adkim] != "" {
mutate {
replace => { "f_adkim.key" => "dkim_alignment_mode" "f_adkim.value.string_value" => "%{adkim}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_adkim" }
}
}
if [aspf] {
if [aspf] != "" {
mutate {
replace => { "f_aspf.key" => "spf_alignment_mode" "f_aspf.value.string_value" => "%{aspf}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_aspf" }
@@ -403,7 +412,7 @@ filter {
merge => { "event.idm.read_only_udm.additional.fields" => "f_testing" }
}
}
if [discovery_method] {
if [discovery_method] != "" {
mutate {
replace => { "f_disc.key" => "discovery_method" "f_disc.value.string_value" => "%{discovery_method}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_disc" }
@@ -435,7 +444,7 @@ filter {
merge => { "event.idm.read_only_udm.additional.fields" => "f_dkima" }
}
}
if [disposition] {
if [disposition] != "" {
mutate {
replace => { "f_disp.key" => "disposition" "f_disp.value.string_value" => "%{disposition}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_disp" }
@@ -443,37 +452,37 @@ filter {
}
# DKIM / SPF auth detail (comma-joined by parsedmarc).
if [dkim_domains] {
if [dkim_domains] != "" {
mutate {
replace => { "f_dkd.key" => "dkim_domains" "f_dkd.value.string_value" => "%{dkim_domains}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_dkd" }
}
}
if [dkim_selectors] {
if [dkim_selectors] != "" {
mutate {
replace => { "f_dks.key" => "dkim_selectors" "f_dks.value.string_value" => "%{dkim_selectors}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_dks" }
}
}
if [dkim_results] {
if [dkim_results] != "" {
mutate {
replace => { "f_dkr.key" => "dkim_results" "f_dkr.value.string_value" => "%{dkim_results}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_dkr" }
}
}
if [spf_domains] {
if [spf_domains] != "" {
mutate {
replace => { "f_spd.key" => "spf_domains" "f_spd.value.string_value" => "%{spf_domains}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_spd" }
}
}
if [spf_scopes] {
if [spf_scopes] != "" {
mutate {
replace => { "f_sps.key" => "spf_scopes" "f_sps.value.string_value" => "%{spf_scopes}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_sps" }
}
}
if [spf_results] {
if [spf_results] != "" {
mutate {
replace => { "f_spr.key" => "spf_results" "f_spr.value.string_value" => "%{spf_results}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_spr" }
@@ -481,13 +490,13 @@ filter {
}
# Policy overrides (parsedmarc writes the literal "none" when there are none).
if [policy_override_reasons] and [policy_override_reasons] != "none" {
if [policy_override_reasons] != "" and [policy_override_reasons] != "none" {
mutate {
replace => { "f_por.key" => "policy_override_reasons" "f_por.value.string_value" => "%{policy_override_reasons}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_por" }
}
}
if [policy_override_comments] and [policy_override_comments] != "none" {
if [policy_override_comments] != "" and [policy_override_comments] != "none" {
mutate {
replace => { "f_poc.key" => "policy_override_comments" "f_poc.value.string_value" => "%{policy_override_comments}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_poc" }
@@ -495,37 +504,42 @@ filter {
}
# Source enrichment from parsedmarc's reverse-DNS / MMDB maps.
if [source_base_domain] {
if [source_base_domain] != "" {
mutate {
replace => { "f_sbd.key" => "source_base_domain" "f_sbd.value.string_value" => "%{source_base_domain}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_sbd" }
}
}
if [source_name] {
if [source_name] != "" {
mutate {
replace => { "f_sn.key" => "source_name" "f_sn.value.string_value" => "%{source_name}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_sn" }
}
}
if [source_type] {
if [source_type] != "" {
mutate {
replace => { "f_st.key" => "source_type" "f_st.value.string_value" => "%{source_type}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_st" }
}
}
if [source_asn] {
mutate {
replace => { "f_asn.key" => "source_asn" "f_asn.value.string_value" => "%{source_asn}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_asn" }
}
mutate {
replace => { "f_asn.key" => "source_asn" "f_asn.value.string_value" => "%{source_asn}" }
}
if [source_as_name] {
mutate {
convert => { "f_asn.value.string_value" => "uinteger" }
on_error => "asn_nan"
}
if ![asn_nan] {
mutate { rename => { "f_asn.value.string_value" => "f_asn.value.number_value" } }
mutate { merge => { "event.idm.read_only_udm.additional.fields" => "f_asn" } }
}
if [source_as_name] != "" {
mutate {
replace => { "f_asnm.key" => "source_as_name" "f_asnm.value.string_value" => "%{source_as_name}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_asnm" }
}
}
if [source_as_domain] {
if [source_as_domain] != "" {
mutate {
replace => { "f_asd.key" => "source_as_domain" "f_asd.value.string_value" => "%{source_as_domain}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_asd" }
@@ -533,13 +547,13 @@ filter {
}
# Envelope identifiers (usually empty in aggregate reports).
if [envelope_from] {
if [envelope_from] != "" {
mutate {
replace => { "f_ef.key" => "envelope_from" "f_ef.value.string_value" => "%{envelope_from}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_ef" }
}
}
if [envelope_to] {
if [envelope_to] != "" {
mutate {
replace => { "f_et.key" => "envelope_to" "f_et.value.string_value" => "%{envelope_to}" }
merge => { "event.idm.read_only_udm.additional.fields" => "f_et" }
@@ -554,7 +568,7 @@ filter {
mutate { replace => { "event_type" => "EMAIL_TRANSACTION" } }
if [message_id] {
if [message_id] != "" {
mutate {
replace => {
"event.idm.read_only_udm.metadata.product_log_id" => "%{message_id}"
@@ -563,7 +577,7 @@ filter {
}
# -- event timestamp: message arrival time (UTC). --
if [arrival_date_utc] {
if [arrival_date_utc] != "" {
date {
match => ["arrival_date_utc", "yyyy-MM-dd HH:mm:ss"]
timezone => "UTC"
@@ -572,20 +586,20 @@ filter {
}
# -- principal: the sending source. --
if [source_ip_address] {
if [source_ip_address] != "" {
mutate {
merge => { "event.idm.read_only_udm.principal.ip" => "source_ip_address" }
on_error => "fail_src_ip_error"
}
}
if [source_reverse_dns] {
if [source_reverse_dns] != "" {
mutate {
replace => {
"event.idm.read_only_udm.principal.hostname" => "%{source_reverse_dns}"
}
}
}
if [source_country] {
if [source_country] != "" {
mutate {
replace => {
"event.idm.read_only_udm.principal.location.country_or_region" => "%{source_country}"
@@ -594,7 +608,7 @@ filter {
}
# -- target: the reported (claimed) domain. --
if [reported_domain] {
if [reported_domain] != "" {
mutate {
replace => {
"event.idm.read_only_udm.target.hostname" => "%{reported_domain}"
@@ -603,14 +617,14 @@ filter {
}
# -- email: failure reports carry full addresses + subject. --
if [original_mail_from] {
if [original_mail_from] != "" {
mutate {
replace => {
"event.idm.read_only_udm.network.email.from" => "%{original_mail_from}"
}
}
}
if [original_rcpt_to] {
if [original_rcpt_to] != "" {
mutate {
replace => {
"event.idm.read_only_udm.network.email.to" => "%{original_rcpt_to}"
@@ -618,14 +632,14 @@ filter {
on_error => "fail_rcpt_error"
}
}
if [subject] {
if [subject] != "" {
mutate {
replace => {
"event.idm.read_only_udm.network.email.subject" => "%{subject}"
}
}
}
if [message_id] {
if [message_id] != "" {
mutate {
replace => {
"event.idm.read_only_udm.network.email.mail_id" => "%{message_id}"
@@ -649,7 +663,7 @@ filter {
} else {
mutate { replace => { "srf.action" => "UNKNOWN_ACTION" } }
}
if [auth_failure] {
if [auth_failure] != "" {
mutate {
replace => {
"srf.description" => "auth_failure=%{auth_failure} delivery_result=%{delivery_result}"
@@ -662,49 +676,49 @@ filter {
}
# -- additional.fields. --
if [feedback_type] {
if [feedback_type] != "" {
mutate {
replace => { "g_fb.key" => "feedback_type" "g_fb.value.string_value" => "%{feedback_type}" }
merge => { "event.idm.read_only_udm.additional.fields" => "g_fb" }
}
}
if [auth_failure] {
if [auth_failure] != "" {
mutate {
replace => { "g_af.key" => "auth_failure" "g_af.value.string_value" => "%{auth_failure}" }
merge => { "event.idm.read_only_udm.additional.fields" => "g_af" }
}
}
if [delivery_result] {
if [delivery_result] != "" {
mutate {
replace => { "g_dr.key" => "delivery_result" "g_dr.value.string_value" => "%{delivery_result}" }
merge => { "event.idm.read_only_udm.additional.fields" => "g_dr" }
}
}
if [authentication_results] {
if [authentication_results] != "" {
mutate {
replace => { "g_ar.key" => "authentication_results" "g_ar.value.string_value" => "%{authentication_results}" }
merge => { "event.idm.read_only_udm.additional.fields" => "g_ar" }
}
}
if [authentication_mechanisms] {
if [authentication_mechanisms] != "" {
mutate {
replace => { "g_am.key" => "authentication_mechanisms" "g_am.value.string_value" => "%{authentication_mechanisms}" }
merge => { "event.idm.read_only_udm.additional.fields" => "g_am" }
}
}
if [user_agent] {
if [user_agent] != "" {
mutate {
replace => { "g_ua.key" => "user_agent" "g_ua.value.string_value" => "%{user_agent}" }
merge => { "event.idm.read_only_udm.additional.fields" => "g_ua" }
}
}
if [dkim_domain] {
if [dkim_domain] != "" {
mutate {
replace => { "g_dd.key" => "dkim_domain" "g_dd.value.string_value" => "%{dkim_domain}" }
merge => { "event.idm.read_only_udm.additional.fields" => "g_dd" }
}
}
if [arrival_date] {
if [arrival_date] != "" {
mutate {
replace => { "g_ad.key" => "arrival_date" "g_ad.value.string_value" => "%{arrival_date}" }
merge => { "event.idm.read_only_udm.additional.fields" => "g_ad" }
@@ -722,7 +736,7 @@ filter {
mutate { replace => { "event_type" => "GENERIC_EVENT" } }
if [report_id] {
if [report_id] != "" {
mutate {
replace => {
"event.idm.read_only_udm.metadata.product_log_id" => "%{report_id}"
@@ -732,7 +746,7 @@ filter {
# -- event timestamp: start of the report window. SMTP TLS uses ISO 8601
# with a trailing Z (e.g. 2025-12-07T19:00:00Z), unlike the other types. --
if [begin_date] {
if [begin_date] != "" {
date {
match => ["begin_date", "yyyy-MM-dd'T'HH:mm:ss'Z'"]
timezone => "UTC"
@@ -741,7 +755,7 @@ filter {
}
# -- target: the reported policy domain (always present -> the noun). --
if [policy_domain] {
if [policy_domain] != "" {
mutate {
replace => {
"event.idm.read_only_udm.target.hostname" => "%{policy_domain}"
@@ -749,14 +763,14 @@ filter {
}
}
# receiving MTA IP, when a per-session failure row carries it.
if [receiving_ip] {
if [receiving_ip] != "" {
mutate {
merge => { "event.idm.read_only_udm.target.ip" => "receiving_ip" }
on_error => "tls_rcv_ip_error"
}
}
# sending MTA IP, when present, is the principal.
if [sending_mta_ip] {
if [sending_mta_ip] != "" {
mutate {
merge => { "event.idm.read_only_udm.principal.ip" => "sending_mta_ip" }
on_error => "tls_snd_ip_error"
@@ -764,7 +778,7 @@ filter {
}
# -- security_result only on failures (result_type present). --
if [result_type] {
if [result_type] != "" {
mutate {
replace => {
"srt.summary" => "SMTP TLS report failure"
@@ -780,85 +794,95 @@ filter {
}
# -- additional.fields. --
if [organization_name] {
if [organization_name] != "" {
mutate {
replace => { "t_org.key" => "organization_name" "t_org.value.string_value" => "%{organization_name}" }
merge => { "event.idm.read_only_udm.additional.fields" => "t_org" }
}
}
if [begin_date] {
if [begin_date] != "" {
mutate {
replace => { "t_begin.key" => "begin_date" "t_begin.value.string_value" => "%{begin_date}" }
merge => { "event.idm.read_only_udm.additional.fields" => "t_begin" }
}
}
if [end_date] {
if [end_date] != "" {
mutate {
replace => { "t_end.key" => "end_date" "t_end.value.string_value" => "%{end_date}" }
merge => { "event.idm.read_only_udm.additional.fields" => "t_end" }
}
}
if [policy_domain] {
if [policy_domain] != "" {
mutate {
replace => { "t_pd.key" => "policy_domain" "t_pd.value.string_value" => "%{policy_domain}" }
merge => { "event.idm.read_only_udm.additional.fields" => "t_pd" }
}
}
if [policy_type] {
if [policy_type] != "" {
mutate {
replace => { "t_pt.key" => "policy_type" "t_pt.value.string_value" => "%{policy_type}" }
merge => { "event.idm.read_only_udm.additional.fields" => "t_pt" }
}
}
if [policy_strings] {
if [policy_strings] != "" {
mutate {
replace => { "t_ps.key" => "policy_strings" "t_ps.value.string_value" => "%{policy_strings}" }
merge => { "event.idm.read_only_udm.additional.fields" => "t_ps" }
}
}
if [mx_host_patterns] {
if [mx_host_patterns] != "" {
mutate {
replace => { "t_mx.key" => "mx_host_patterns" "t_mx.value.string_value" => "%{mx_host_patterns}" }
merge => { "event.idm.read_only_udm.additional.fields" => "t_mx" }
}
}
if [successful_session_count] {
mutate {
replace => { "t_ssc.key" => "successful_session_count" "t_ssc.value.string_value" => "%{successful_session_count}" }
merge => { "event.idm.read_only_udm.additional.fields" => "t_ssc" }
}
mutate {
replace => { "t_ssc.key" => "successful_session_count" "t_ssc.value.string_value" => "%{successful_session_count}" }
}
if [failed_session_count] {
mutate {
replace => { "t_fsc.key" => "failed_session_count" "t_fsc.value.string_value" => "%{failed_session_count}" }
merge => { "event.idm.read_only_udm.additional.fields" => "t_fsc" }
}
mutate {
convert => { "t_ssc.value.string_value" => "uinteger" }
on_error => "ssc_nan"
}
if [result_type] {
if ![ssc_nan] {
mutate { rename => { "t_ssc.value.string_value" => "t_ssc.value.number_value" } }
mutate { merge => { "event.idm.read_only_udm.additional.fields" => "t_ssc" } }
}
mutate {
replace => { "t_fsc.key" => "failed_session_count" "t_fsc.value.string_value" => "%{failed_session_count}" }
}
mutate {
convert => { "t_fsc.value.string_value" => "uinteger" }
on_error => "fsc_nan"
}
if ![fsc_nan] {
mutate { rename => { "t_fsc.value.string_value" => "t_fsc.value.number_value" } }
mutate { merge => { "event.idm.read_only_udm.additional.fields" => "t_fsc" } }
}
if [result_type] != "" {
mutate {
replace => { "t_rt.key" => "result_type" "t_rt.value.string_value" => "%{result_type}" }
merge => { "event.idm.read_only_udm.additional.fields" => "t_rt" }
}
}
if [failure_reason_code] {
if [failure_reason_code] != "" {
mutate {
replace => { "t_frc.key" => "failure_reason_code" "t_frc.value.string_value" => "%{failure_reason_code}" }
merge => { "event.idm.read_only_udm.additional.fields" => "t_frc" }
}
}
if [receiving_mx_hostname] {
if [receiving_mx_hostname] != "" {
mutate {
replace => { "t_rmh.key" => "receiving_mx_hostname" "t_rmh.value.string_value" => "%{receiving_mx_hostname}" }
merge => { "event.idm.read_only_udm.additional.fields" => "t_rmh" }
}
}
if [receiving_mx_helo] {
if [receiving_mx_helo] != "" {
mutate {
replace => { "t_rmhelo.key" => "receiving_mx_helo" "t_rmhelo.value.string_value" => "%{receiving_mx_helo}" }
merge => { "event.idm.read_only_udm.additional.fields" => "t_rmhelo" }
}
}
if [additional_info_uri] {
if [additional_info_uri] != "" {
mutate {
replace => { "t_aiu.key" => "additional_info_uri" "t_aiu.value.string_value" => "%{additional_info_uri}" }
merge => { "event.idm.read_only_udm.additional.fields" => "t_aiu" }
@@ -876,7 +900,7 @@ filter {
"event.idm.read_only_udm.metadata.product_name" => "parsedmarc"
}
}
if [report_type] {
if [report_type] != "" {
mutate {
replace => {
"event.idm.read_only_udm.metadata.product_event_type" => "%{report_type}"