rsigma-convert
rsigma-convert
Convert Sigma rules into backend-native query strings. A rule is lowered to the intermediate representation (rsigma-ir) once, and the Backend trait renders from that HIR; ships with PostgreSQL/TimescaleDB, LynxDB, and Fibratus backends, and lets you add your own.
When to use
- Generate SQL for an existing log store: PostgreSQL, TimescaleDB.
- Generate SPL2 for LynxDB.
- Build a custom backend (Elasticsearch DSL, Loki LogQL, ClickHouse SQL, Splunk SPL, KQL, anything that can be expressed as a text query). Implement
Backendonce and reuse the rule-walking machinery.
For event evaluation (running rules against in-memory events), use rsigma-eval.
Install
[dependencies]
rsigma-parser = "0.21.0"
rsigma-convert = "0.21.0"
No features. The crate is pure Rust + regex.
Public surface
| Type | Purpose |
|---|---|
Backend trait |
The plug-in surface. Value leaves consume the faithful HIR (IrPattern, IrStrOp, IrNumber, RegexFlags, CompareOp) with no parser types; implement one leaf per matcher shape and return the query as a string. |
TextQueryConfig |
~90-field config struct that drives most text-query backends declaratively. Mirrors pySigma’s TextQueryBackend class variables (precedence, boolean operators, wildcards, string and field quoting, regex and CIDR templates, IN-list optimization, deferred parts, query envelope). |
PostgresBackend |
The PostgreSQL/TimescaleDB backend. Output formats: default, view, timescaledb, continuous_aggregate, sliding_window. |
LynxDbBackend |
The LynxDB backend. Output formats: default, minimal. |
FibratusBackend |
The Fibratus backend. Output formats: default, expr, yaml, rule. |
TextQueryTestBackend |
A backend-neutral text format used by the test suite and useful for debugging how a rule lowers to a generic boolean expression. |
convert_collection(backend, &SigmaCollection, &[Pipeline], output_format) |
Convert a whole collection, applying pipelines per rule. Returns a ConversionOutput with per-rule queries and per-rule errors. |
Backend::convert_rule(rule, output_format, &PipelineState) |
Lower-level single-rule entry point on the trait. |
ConversionOutput, ConversionResult, ConversionState, PipelineState |
Collection/result wrappers, the per-condition conversion state (ConversionState), and the per-rule pipeline state (PipelineState from rsigma-eval). |
The full Backend trait method list and the per-backend modifier mapping are in the crate README and in the PostgreSQL and LynxDB backend references.
Minimum example
use rsigma_convert::{convert_collection, backends::postgres::PostgresBackend};
use rsigma_parser::parse_sigma_yaml;
let rule_yaml = r#"
title: Whoami
id: 8b1d8c97-5b3a-4d77-9b48-7c5f7c8b1a2a
logsource: { product: windows, category: process_creation }
detection:
selection:
CommandLine|contains: 'whoami'
condition: selection
"#;
let collection = parse_sigma_yaml(rule_yaml)?;
let backend = PostgresBackend::new();
let output = convert_collection(&backend, &collection, &[], "default")?;
for result in &output.queries {
for q in &result.queries {
println!("-- {}\n{}\n", result.rule_title, q);
}
}
// -- Whoami
// SELECT * FROM security_events WHERE "CommandLine" ILIKE '%whoami%'
Backend options
PostgresBackend::from_options(&HashMap<String, String>) reads the CLI -O key=value map. Recognised keys:
| Key | Effect |
|---|---|
table |
Default table name (default security_events). |
schema |
PostgreSQL schema. |
database |
Connection-level metadata for some output formats. |
timestamp_field |
Column name for the timestamp (default time). |
json_field |
Treat field references as JSONB extraction paths in this column. |
case_sensitive_re |
Use ~ instead of ~* for regex. |
LynxDB has no CLI -O options; its only knob is the target index, controlled via pipeline set_state with key: index (default main).
Writing a custom backend
The smallest viable backend implements Backend, returns a TextQueryConfig, and lets the trait’s default methods do the heavy lifting:
use rsigma_convert::{Backend, TextQueryConfig, TokenType};
pub struct MyBackend;
static MY_CONFIG: TextQueryConfig = TextQueryConfig {
precedence: (TokenType::NOT, TokenType::AND, TokenType::OR),
group_expression: "({expr})",
token_separator: " ",
and_token: "AND",
or_token: "OR",
not_token: "NOT",
eq_token: " = ",
not_eq_token: Some(" <> "),
// ... 80+ other knobs, see the docs.rs page
.. TextQueryConfig::PYSIGMA_DEFAULTS
};
impl Backend for MyBackend {
fn name(&self) -> &str { "my_backend" }
fn formats(&self) -> &[(&str, &str)] {
&[("default", "Plain MyBackend query")]
}
fn text_query_config(&self) -> Option<&TextQueryConfig> {
Some(&MY_CONFIG)
}
}
The default convert_rule lowers the rule to IrRule, walks the resulting IrDetection and IrCondition, and dispatches into text_* helpers (e.g. text_convert_field_str_ir, text_convert_ir_pattern) that consult the config. Only override the leaves that your backend needs to behave differently from pySigma’s TextQueryBackend default.
See Adding Backends for the step-by-step walkthrough, the testing pattern, and how to wire a new backend into rsigma backend convert if you also want CLI integration.
Error handling
ConvertError from thiserror. Variants include RuleConversion (a rule could not be converted with the chosen backend or format), UnsupportedModifier, InvalidIdentifier (table/schema name failed validation), and Pipeline (a pre-conversion pipeline step failed).
See also
- Rule Conversion for the operator-facing workflow.
- PostgreSQL backend reference, LynxDB backend reference, and Fibratus backend reference.
- Adding Backends for the contributor walkthrough.
rsigma-convertREADME for the full Backend trait reference.- docs.rs/rsigma-convert.