Skip to main content

rsigma_eval/
lib.rs

1//! # rsigma-eval
2//!
3//! Evaluator for Sigma detection and correlation rules.
4//!
5//! This crate consumes the AST produced by [`rsigma_parser`] and evaluates it
6//! against events in real time using a compile-then-evaluate model.
7//!
8//! ## Architecture
9//!
10//! - **Detection rules** (stateless): compiled once into optimized matchers,
11//!   each event is matched with zero allocation on the hot path.
12//! - **Correlation rules** (stateful): time-windowed aggregation over detection
13//!   matches, supporting `event_count`, `value_count`, `temporal`,
14//!   `temporal_ordered`, `value_sum`, `value_avg`, `value_percentile`,
15//!   and `value_median`.
16//!
17//! ## Quick Start — Detection Only
18//!
19//! ```rust
20//! use rsigma_parser::parse_sigma_yaml;
21//! use rsigma_eval::Engine;
22//! use rsigma_eval::event::JsonEvent;
23//! use serde_json::json;
24//!
25//! let yaml = r#"
26//! title: Detect Whoami
27//! logsource:
28//!     product: windows
29//!     category: process_creation
30//! detection:
31//!     selection:
32//!         CommandLine|contains: 'whoami'
33//!     condition: selection
34//! level: medium
35//! "#;
36//!
37//! let collection = parse_sigma_yaml(yaml).unwrap();
38//! let mut engine = Engine::new();
39//! engine.add_collection(&collection).unwrap();
40//!
41//! let event_val = json!({"CommandLine": "cmd /c whoami"});
42//! let event = JsonEvent::borrow(&event_val);
43//! let matches = engine.evaluate(&event);
44//! assert_eq!(matches.len(), 1);
45//! ```
46//!
47//! ## Quick Start — With Correlations
48//!
49//! ```rust
50//! use rsigma_parser::parse_sigma_yaml;
51//! use rsigma_eval::{CorrelationEngine, CorrelationConfig};
52//! use rsigma_eval::event::JsonEvent;
53//! use serde_json::json;
54//!
55//! let yaml = r#"
56//! title: Login
57//! id: login-rule
58//! logsource:
59//!     category: auth
60//! detection:
61//!     selection:
62//!         EventType: login
63//!     condition: selection
64//! ---
65//! title: Many Logins
66//! correlation:
67//!     type: event_count
68//!     rules:
69//!         - login-rule
70//!     group-by:
71//!         - User
72//!     timespan: 60s
73//!     condition:
74//!         gte: 3
75//! level: high
76//! "#;
77//!
78//! let collection = parse_sigma_yaml(yaml).unwrap();
79//! let mut engine = CorrelationEngine::new(CorrelationConfig::default());
80//! engine.add_collection(&collection).unwrap();
81//!
82//! for i in 0..3 {
83//!     let v = json!({"EventType": "login", "User": "admin"});
84//!     let event = JsonEvent::borrow(&v);
85//!     let result = engine.process_event_at(&event, 1000 + i);
86//!     if i == 2 {
87//!         let correlations = result.iter().filter(|r| r.is_correlation()).count();
88//!         assert_eq!(correlations, 1);
89//!     }
90//! }
91//! ```
92
93mod candidate_index;
94pub mod compiler;
95pub mod correlation;
96pub mod correlation_engine;
97pub mod engine;
98pub mod error;
99pub mod event;
100pub mod exemplar;
101pub mod explain;
102pub mod field_observer;
103pub mod fields;
104mod key_shape;
105pub mod logsource;
106pub mod matcher;
107pub mod pipeline;
108pub mod result;
109pub mod router;
110pub mod rule_draft;
111pub mod rule_metadata;
112pub mod rule_tune;
113pub mod schema;
114pub mod schema_discovery;
115mod witness;
116
117// Re-export the most commonly used types and functions at crate root
118pub use compiler::{
119    CompiledDetection, CompiledDetectionItem, CompiledRule, compile_rule, compile_to_compiled,
120    evaluate_rule,
121};
122pub use correlation::{
123    CompiledCondition, CompiledCorrelation, EventBuffer, EventRef, EventRefBuffer, GroupByField,
124    GroupKey, WindowState,
125};
126pub use correlation_engine::{
127    CorrelationAction, CorrelationConfig, CorrelationEngine, CorrelationEventMode, CorrelationInfo,
128    CorrelationSnapshot, CorrelationStateSnapshot, GroupKeyPart, GroupStateInfo, ProcessResult,
129    TimestampFallback,
130};
131pub use engine::Engine;
132pub use error::{EvalError, Result};
133pub use event::{Event, EventValue, JsonEvent, KvEvent, MapEvent, MappedEvent, PlainEvent};
134pub use exemplar::{
135    ExemplarReport, ExemplarResult, ExemplarRunError, MissingExemplars, run_exemplars,
136};
137pub use explain::{
138    ArrayEmptyReason, ArrayMemberTrace, ConditionTrace, DetectionTrace, ItemTrace, MatchReason,
139    RuleExplanation, SelectionBranch, explain_rule,
140};
141pub use field_observer::{FieldCoverage, FieldObservation, FieldObservationEntry, FieldObserver};
142pub use fields::{FieldOrigin, FieldSource, RuleFieldSet};
143pub use logsource::LogSourceExtractor;
144pub use matcher::{CompiledMatcher, MatchDescriptor};
145pub use pipeline::{
146    Pipeline, PipelineState, TransformationItem, TransformedRule, apply_pipelines,
147    apply_pipelines_with_state,
148    builtin::{
149        builtin_names as builtin_pipeline_names, resolve_builtin as resolve_builtin_pipeline,
150    },
151    merge_pipelines, parse_pipeline, parse_pipeline_file, parse_sources, parse_sources_dir,
152    parse_sources_file, parse_transformation_items, transform_collection, transform_rule,
153    validate_source_refs,
154};
155pub use result::{
156    CorrelationBody, DetectionBody, EvaluationResult, FieldMatch, MatchDetailLevel, MatcherKind,
157    ProcessResultExt, ResultBody, RuleHeader,
158};
159pub use router::{RouteOutcome, RouteResult, SchemaPruning, SchemaRouter};
160pub use rule_draft::{
161    DraftConfig, DraftError, DraftFieldReport, DraftReport, Stability, draft_rule,
162};
163pub use rule_metadata::{RuleBundleMetadata, RuleIdentity, RuleKind, RuleMetadataLookup};
164pub use rule_tune::{
165    TuneConfig, TuneError, TuneExpectationDiff, TuneFieldDisposition, TuneFieldReport, TuneReport,
166    TuneSelectionReport, TuneVerification, tune_rule,
167};
168pub use schema::{
169    FieldValueConfig, OnUnknown, PredicateOutcome, RouteDecision, RoutingConfig, RoutingPlan,
170    SchemaBinding, SchemaClassifier, SchemaCountEntry, SchemaError, SchemaExplanation, SchemaMatch,
171    SchemaObservation, SchemaObserver, SchemaPredicate, SchemaPredicateConfig, SchemaSignature,
172    SchemaSignatureConfig, SchemaSignaturesFile, SignatureExplanation, UnknownShapeEntry,
173    builtin_schema_names, load_schema_config, load_schema_signatures, parse_schema_config,
174    parse_schema_signatures, validate_schema_config,
175};
176pub use schema_discovery::{
177    CandidateSource, DiscoveryCandidate, DiscoveryConfig, DiscoveryReport, DiscoveryStats,
178    FieldProfile, cluster_count, mine_events, mine_shapes,
179};