-
Notifications
You must be signed in to change notification settings - Fork 71
Advanced Features
Take your detection and parsing to the next level with advanced correlation and expression language features.
The where field in rules and filters uses a customized version of the Common Expression Language (CEL). Unlike standard CEL which uses method-call syntax (e.g., field.contains()), UTMStack uses functional overloads that are safer and handle missing fields automatically.
| Category | Function | Field Type (Log) | Literal Type (Rule) | Description |
|---|---|---|---|---|
| Existence | exists("f") |
Any | N/A | Checks if a field exists. |
| Logic | safe("f", def) |
String, Num, Bool | Matches Field | Returns field value or def if missing. |
| String | equals("f", "v") |
String, Num | Matches Field | Case-sensitive equality check. |
equalsIgnoreCase |
String | String | Case-insensitive equality. | |
contains |
String | String or List | True if field contains substring(s). | |
containsAll |
String | List of Strings | True if field contains all substrings. | |
startsWith |
String | String or List | True if field starts with prefix(es). | |
endsWith |
String | String or List | True if field ends with suffix(es). | |
regexMatch |
String | String (Regex) | Validates field against a regex. | |
| Network | inCIDR("f", "net") |
String (IP) | String (CIDR) | IPv4/v6 within a CIDR range. |
| Comparison | greaterThan |
Number | String, Int, Double | True if field > value. |
lessThan |
Number | String, Int, Double | True if field < value. | |
greaterOrEqual |
Number | String, Int, Double | True if field >= value. | |
lessOrEqual |
Number | String, Int, Double | True if field <= value. | |
| Lists | oneOf("f", [...]) |
Any | List of Any | True if field matches any item. |
| Temporal | isHour("f", val) |
String (ISO8601) | Int (0-23) | True if hour matches val. |
isMinute("f", val) |
String (ISO8601) | Int (0-59) | True if minute matches val. |
|
isDayOfWeek("f", val) |
String (ISO8601) | Int (0-6) | True if day (0=Sun) matches val. |
|
isWeekend("f") |
String (ISO8601) | N/A | True if Saturday or Sunday. | |
isWorkDay("f") |
String (ISO8601) | N/A | True if Monday to Friday. | |
isBetweenTime("f", "start", "end") |
String (ISO8601) | String ("HH:MM") | True if falls within range. |
where: >
exists("origin.ip") &&
!inCIDR("origin.ip", "10.0.0.0/8") &&
(startsWith("origin.user", "admin_") || equals("origin.user", "root"))Rules can correlate across multiple indices and time windows using afterEvents.
You can check for multiple distinct event patterns:
afterEvents:
- indexPattern: "v11-log-*"
count: 5
within: "now-1h"
with:
- { field: "action", operator: "filter_term", value: "failure" }
- indexPattern: "v11-log-*"
count: 1
within: "now-5m"
with:
- { field: "action", operator: "filter_term", value: "success" }Use the or field within afterEvents to match either of two conditions:
afterEvents:
- indexPattern: "v11-log-*"
within: "now-12h"
count: 1
or:
- indexPattern: "v11-alert-*"
within: "now-24h"
count: 2Filters are not limited to a single pass. You can define multiple stages for the same dataType to handle complex multi-step parsing:
pipeline:
- dataTypes: [syslog]
steps:
- grok:
source: raw
patterns:
- fieldName: log.message
pattern: '{{.greedy}}'
- dataTypes: [syslog]
steps:
- json:
source: log.messageThis modular approach allows you to reuse common parsing logic across different log variants.