Convert CEF
Convert a CEF (Common Event Format) event from a field into structured output — header fields, extension key-values, column mapping with presets, and overflow collection.
Overview
The Convert CEF transformation parses a raw CEF line (e.g. CEF:0|Vendor|Product|1.0|100|Name|5|src=10.0.0.1 act=allow) held in a record field into a structured record. The seven CEF header slots become named fields, each key=value extension pair is mapped to an output column, and anything you haven't mapped is either collected into a single overflow field or emitted as an individual field.
- Presets —
common_security_log(Microsoft Sentinel CommonSecurityLog column names) andcef_full_names(ArcSight dictionary names) supply a full column map, header field names, and a default list of numeric columns, so most configurations only need the preset. Your owncolumnsentries are laid over the preset key by key. - Output modes — replace the record with the parsed object, merge the parsed fields into the record, or nest the parsed object under a key.
- Lenient by default — every record produces output; structural problems (no CEF marker, truncated header, invalid escapes) are handled best-effort and optionally reported as warnings. Set
strict: trueto error instead.
Dialects
The transform parses two dialects, selected with the dialect argument:
- CEF (
cef, default) — spec-faithful parsing. TheCEF:marker is found anywhere in the line (a syslog prefix before it is skipped, and a space betweenCEF:and the version digit is tolerated). Escaped pipes (\|) in header fields do not delimit, and extension values are unescaped (\\,\=,\n,\r). Extension keys start with an alphanumeric or_and may then contain_ . , - [ ]. Trailing whitespace is trimmed from the final extension value only. - Legacy key-value (
legacy_kv) — compatible with simpler line-oriented CEF parsers. A literalCEF:prefix is stripped only at the very start of the line, every pipe delimits a header field (escapes are ignored), no unescaping is performed anywhere, extension keys are strictly alphanumeric (starting with a letter), and the final value keeps its trailing whitespace. Use this dialect when you need output identical to an existing pipeline built on those rules.
In both dialects, a new extension pair starts only at a space immediately followed by a key and =. Anything else — unescaped = signs inside URLs, tabs, extra spaces — is absorbed into the previous value.
Presets
common_security_log— 132 CEF key → column mappings (src→SourceIP,dst→DestinationIP,dpt→DestinationPort,act→DeviceAction,msg→Message, the full custom-string/number/IPv6/flex families →DeviceCustomString1…, and so on), Sentinel-style header names (CefVersion,DeviceVendor,DeviceProduct,DeviceVersion,DeviceEventClassID,Activity,LogSeverity), 22 numeric columns (ports, byte counts, process IDs, custom numbers), and a defaultoverflow_fieldofAdditionalExtensions(applied only if you leaveoverflow_fieldempty). The preset targets the table's current columns:cn1-cn3map toFieldDeviceCustomNumber1-FieldDeviceCustomNumber3andexternalIdmaps toExtID, not the deprecatedDeviceCustomNumber1-3andExternalIDthat Microsoft's older CEF mapping lists.ExtIDis a string column, so non-numeric IDs such asABC-123pass through intact.cef_full_names— 117 mappings to ArcSight dictionary names (src→sourceAddress,dst→destinationAddress,spt→sourcePort,msg→message,rt→deviceReceiptTime, …), lower-camel header names (cefVersion,deviceVendor,deviceProduct,deviceVersion,deviceEventClassId,name,severity), and 17 numeric columns. This preset does not default the overflow field.- No preset (default) — no column map (every extension key is unmapped), no numeric coercion, and the same lower-camel header names as
cef_full_names.
Configuration
| Argument | Type | Required | Default | Description |
|---|---|---|---|---|
key | string | No | "message" | JSONPath to the record field holding the CEF line. A missing or null source is parsed as an empty line (see Notes); a non-string value is parsed from its raw JSON text with a non_string_source warning. |
dialect | string | No | "cef" | Parsing dialect: "cef" (spec-faithful) or "legacy_kv" (see Dialects). |
output_mode | string | No | "replace" | How the parsed object is written back: "replace", "merge", or "under_key" (see Output Behavior). |
output_key | string | Yes (for under_key) | - | JSONPath where the parsed object is nested when output_mode is "under_key". |
preset | string | No | - | Column-mapping preset: "common_security_log" or "cef_full_names". Supplies the column map, default header names, and default numeric columns. |
columns | object | No | - | Map of CEF extension key → output column name. Merged over the preset map key by key, so individual entries override the preset. Keys absent from the merged map go to the overflow field (or become individual output fields when no overflow field is set). |
header_fields | array | No | per preset | Output names for the 7 CEF header slots (version, device vendor, device product, device version, event class ID, name, severity). Must name exactly 7 fields; replaces the preset's names entirely. |
envelope | object | No | - | Map of output field name → JSONPath into the input record. Each value is copied verbatim (any JSON type) from the original record into the output; a missing path yields null. Envelope fields are emitted first, in alphabetical order. |
overflow_field | string | No (Yes for spill with a marker) | "AdditionalExtensions" with the common_security_log preset, otherwise - | Field collecting unmapped extension keys as key=value entries in encounter order. When configured it is always emitted — null if nothing overflowed. When empty, unmapped keys become individual output fields instead. |
overflow_separator | string | No | ";" | Separator placed between overflow entries. |
continuation_marker | string | No | - | Marker that indicates a continuation inside a value, e.g. "#012" (rsyslog) or "#LF#". Empty disables continuation handling. |
continuation_mode | string | No | "spill" | What to do at a continuation marker: "spill" (keep the value up to the first marker, move the tail to the overflow field), "newline" (replace every marker with a newline), or "keep" (leave values untouched). "spill" with a marker requires overflow_field. |
strip_quotes | boolean | No | false | Remove one pair of surrounding double quotes from extension values that carry both. Applied before continuation handling and unescaping. Not part of the CEF standard. |
empty_to_null | boolean | No | false | Write empty header, extension, and promoted-label values as null instead of "". For envelope fields, only a value that is exactly the JSON string "" becomes null. |
resolve_labels | boolean | No | false | Promote custom-field label pairs: when both a slot (e.g. cs1) and its label (cs1Label) are present, emit an additional field named by the label text holding the slot value. The raw slot and label columns are always kept. Never overwrites an existing field (skipped with a label_collision warning). |
numeric_columns | array | No | preset numeric list | Output column names whose values are coerced to JSON numbers. Leaving it unset uses the preset's numeric list; an explicit [] disables coercion entirely; an explicit list replaces the preset list. Header field names are eligible too. Values that do not parse as numbers become null (see Notes). |
iso_date_columns | array | No | - | Output column names whose values of the exact shape YYYY/MM/DD HH:MM:SS are rewritten to YYYY-MM-DDTHH:MM:SSZ. Non-matching values are left for numeric/string handling. |
strict | boolean | No | false | Fail on structural problems (missing source, no CEF marker, truncated header, invalid escapes, unmergeable record) instead of best-effort parsing with warnings. |
warnings_key | string | No | - | Output field for parse warnings. When set, it is always emitted as an array of strings — [] when the record parsed cleanly. When empty, warnings are dropped. |
Examples
Example 1: Sentinel-style parsing with a preset
Parse a firewall CEF line into CommonSecurityLog column names using the common_security_log preset. The preset supplies the column map, the header names, the numeric columns, and the AdditionalExtensions overflow field.
Code
Given the input record:
Code
The output record will be:
Code
src, dst, dpt, and act are mapped by the preset; DestinationPort is on the preset's numeric list, so 443 is emitted as a number. PanOSApp is not in the preset map, so it lands in AdditionalExtensions. The default output_mode is replace, so the parsed object becomes the entire output record.
Example 2: Custom columns with overflow
Map only the keys you care about and collect everything else into a single field.
Code
Given the input record:
Code
The output record will be:
Code
With no preset, the header slots use the default names (cefVersion through severity) and no numeric coercion applies. The unmapped keys dvc and out are joined into extra as key=value entries, in the order they appear, separated by the default ";".
Output Behavior
replace(default): the parsed object becomes the entire output record; the original fields do not survive. Useenvelopeto carry specific fields from the original record into the output.merge: the parsed fields are merged into the original record at the top level; on a name collision the parsed field wins. If the record is not a JSON object, lenient mode falls back toreplacefor that record and adds amerge_non_objectwarning; strict mode returns an error.under_key: the parsed object is nested atoutput_keyand the rest of the record is preserved. If the write is impossible (for example the record is a top-level array), lenient mode falls back toreplacefor that record; strict mode returns an error.
Output fields are emitted in a deterministic order: envelope fields (alphabetical) → the 7 header fields → the overflow field → mapped and individual columns in the order they were first encountered → the warnings array. If a mapped column shares a name with a header, envelope, or overflow field, the mapped column wins and the other slot is skipped.
Error Handling
With strict: true, the transform will fail with an error in these cases (in lenient mode the same conditions produce best-effort output and, where noted, a warning):
- The source key is missing or
null(lenient: parsed as an empty line) - The source key does not hold a string (lenient: warning
non_string_source) - No CEF marker is found —
cefdialect only (lenient: warningno_cef_marker) - The header has fewer than 7 fields — both dialects (lenient: warning
incomplete_header,cefdialect only) - An extension value contains an invalid escape sequence, e.g. a Windows path like
C:\Users\bob—cefdialect only (lenient: warninginvalid_escape) - The record cannot be merged or written in
merge/under_keymode (lenient: falls back toreplace)
A strict error returns the original record unchanged and aborts the whole batch, so keep strict off unless a malformed record should stop the pipeline. Lenient mode never errors: every record produces output.
The full set of warnings that can appear under warnings_key: no_cef_marker, incomplete_header, invalid_escape, extension_garbage, non_string_source, merge_non_object, label_collision, invalid_utf8. Warnings are de-duplicated per record.
Notes
- A missing source is not a pass-through: when the source key is missing or
null, the line is parsed as if it were empty, producing a skeleton output whose first header field is""and remaining header fields arenull(withempty_to_null, all seven arenull) — the original record is not passed through unchanged. Usestrict: trueif you want missing sources to error instead. - Numeric coercion is lenient: values in
numeric_columnsthat cannot be parsed becomenull— never an error, and never the original string. Leading zeros (007→7), a leading+, and bare-dot forms (.5,5.) are accepted; forms like0x10,1_0,Infinity, andNaNbecomenull. Integers beyond 64-bit range are kept at exact precision. numeric_columnsunset vs empty: omitting the argument uses the preset's numeric list; passing[]explicitly disables coercion; passing a list uses exactly that list. If a column is in bothiso_date_columnsandnumeric_columns, the ISO rewrite wins when the value matches the date shape.iso_date_columnsis textual: the rewrite is a position check on the exactYYYY/MM/DD HH:MM:SSshape with aZappended — no calendar validation and no timezone logic.- Duplicate extension keys: for mapped columns and individual fields, the last occurrence wins. In the overflow field, every occurrence is appended as its own entry.
- Continuation spill format: with
continuation_mode: "spill", a mapped key's tail goes to the overflow field askey::tail(the tail includes the marker); an unmapped key's tail is appended as a separate bare entry with no key. - Header slots that are absent (truncated header) are emitted as
null. Empty header fields are legal and emitted as""(ornullwithempty_to_null). - Base output names must be unique: the 7 header names, envelope field names,
overflow_field, andwarnings_keymust be non-empty and mutually distinct, or the configuration is rejected. - One useful pattern with
replacemode: useenvelopeto pull fields such as a timestamp or hostname from the original record into the parsed output, e.g."envelope": {"EventTime": "timestamp", "Collector": "structured-data.collector.host"}— nested JSONPaths are supported and values are copied verbatim.