Rules¶
Rules are YAML files that define what to query, and under what condition an alert should fire.
Rule file format¶
id: "001"
name: Brute Force Detected
level: 8
size: ">5"
active: true
author:
- Your Name <[email protected]>
group: authentication
tags:
- authentication_failed
- bruteforce
description: "More than 5 failed login attempts in the last minute"
rule: |-
SELECT count(*) AS cnt
FROM auth_logs
WHERE
timestamp >= now() - INTERVAL 1 MINUTE
AND tenant = '{{ detector.tenant }}'
Fields¶
| Field | Required | Description |
|---|---|---|
id |
yes | Unique rule identifier (string) |
name |
yes | Human-readable name |
level |
yes | Severity level (integer, higher = more severe) |
size |
yes | Condition to trigger the alert (see below) |
active |
no | Enable or disable the rule (default: true) |
rule |
yes | Query template (Jinja2, executed against the datasource) |
author |
no | List of authors |
group |
no | Rule group/category |
tags |
no | List of tags for classification |
description |
no | Description of what the rule detects |
data |
no | Custom key/value data, available in the rule template |
size — condition format¶
The size field compares the number of rows returned by the query against a threshold.
| Operator | Example | Meaning |
|---|---|---|
> |
">0" |
At least 1 result |
>= |
">=10" |
10 or more results |
< |
"<5" |
Fewer than 5 results |
<= |
"<=100" |
100 or fewer results |
== |
"==1" |
Exactly 1 result |
Jinja2 templates¶
The rule query is rendered with Jinja2 before execution. The following variables are available:
| Variable | Type | Description |
|---|---|---|
detector.name |
string | Detector name |
detector.tenant |
string | Tenant identifier |
detector.data |
dict | Custom data set in the detector's data field |
rule.id |
string | Rule ID |
rule.name |
string | Rule name |
rule.data |
dict | Custom data set in the rule's data field |
Custom Jinja2 filters¶
| Filter | Description |
|---|---|
\| to_list_like |
Joins items as single-quoted strings: 'a', 'b', 'c' |
\| to_list |
Joins items as comma-separated values: a, b, c |
\| tojson |
Serializes to JSON (handles datetime, UUID, and dataclasses) |
Example with template variables¶
rule: |-
SELECT user, count(*) AS attempts
FROM auth_logs
WHERE
tenant = '{{ detector.tenant }}'
AND status = 'failed'
AND timestamp >= now() - INTERVAL 5 MINUTE
GROUP BY user
HAVING attempts > {{ rule.data.threshold | default(5) }}
data:
threshold: 10
Loading rules in a detector¶
Rules are referenced in the detector's rules list. Both direct paths and glob patterns are supported:
detectors:
my_detector:
rules:
- "rules/auth/brute_force.yml"
- "rules/network/*.yml"
- "rules/**/*.yml"
Webhook alert template variables¶
When a rule fires and a webhook is called, the following variables are available in the webhook template:
| Variable | Description |
|---|---|
rule |
The Rule object (all fields accessible) |
data.len |
Number of rows returned by the query |
data.value |
List of result rows (each row is a dict) |
detector |
The Detector object (name, tenant, data, etc.) |
Tips¶
For more precise query results, use the {{ startime }} and {{ endtime }} parameters. These allow you to filter data within a specific time range, making your queries more efficient and relevant