sentinel_modsec/parser/directive.rs
1//! Directive types for ModSecurity configuration.
2
3use super::{Action, OperatorSpec, VariableSpec};
4use crate::error::SourceLocation;
5use std::path::PathBuf;
6
7/// A parsed ModSecurity directive.
8#[derive(Debug, Clone)]
9pub enum Directive {
10 /// SecRule directive - the main rule type.
11 SecRule(SecRule),
12 /// SecAction directive - actions without matching.
13 SecAction(SecAction),
14 /// SecMarker directive - named marker for skipAfter.
15 SecMarker(SecMarker),
16 /// SecRuleEngine directive - enable/disable rules.
17 SecRuleEngine(RuleEngineMode),
18 /// SecDefaultAction directive - default actions for rules.
19 SecDefaultAction(Vec<Action>),
20 /// SecRuleRemoveById directive - remove rules by ID.
21 SecRuleRemoveById(Vec<u64>),
22 /// SecRuleUpdateActionById directive - update rule actions.
23 SecRuleUpdateActionById { id: u64, actions: Vec<Action> },
24 /// SecRequestBodyAccess directive.
25 SecRequestBodyAccess(bool),
26 /// SecResponseBodyAccess directive.
27 SecResponseBodyAccess(bool),
28 /// SecRequestBodyLimit directive.
29 SecRequestBodyLimit(usize),
30 /// SecResponseBodyLimit directive.
31 SecResponseBodyLimit(usize),
32 /// Include directive - include another file.
33 Include(PathBuf),
34 /// Unknown directive (logged and skipped).
35 Unknown(String),
36}
37
38/// A SecRule directive.
39#[derive(Debug, Clone)]
40pub struct SecRule {
41 /// Variables to inspect.
42 pub variables: Vec<VariableSpec>,
43 /// Operator to apply.
44 pub operator: OperatorSpec,
45 /// Actions to execute on match.
46 pub actions: Vec<Action>,
47 /// Source location for error reporting.
48 pub location: SourceLocation,
49}
50
51/// A SecAction directive.
52#[derive(Debug, Clone)]
53pub struct SecAction {
54 /// Actions to execute.
55 pub actions: Vec<Action>,
56 /// Source location for error reporting.
57 pub location: SourceLocation,
58}
59
60/// A SecMarker directive.
61#[derive(Debug, Clone)]
62pub struct SecMarker {
63 /// Marker name.
64 pub name: String,
65}
66
67/// Rule engine mode.
68#[derive(Debug, Clone, Copy, PartialEq, Eq)]
69pub enum RuleEngineMode {
70 /// Rules are enabled and will block.
71 On,
72 /// Rules are disabled.
73 Off,
74 /// Rules are enabled but will only log, not block.
75 DetectionOnly,
76}
77
78impl Default for RuleEngineMode {
79 fn default() -> Self {
80 Self::Off
81 }
82}
83
84impl SecRule {
85 /// Check if this rule has the chain action.
86 pub fn is_chained(&self) -> bool {
87 self.actions.iter().any(|a| matches!(a, Action::Flow(super::FlowAction::Chain)))
88 }
89
90 /// Get the rule ID if present.
91 pub fn id(&self) -> Option<u64> {
92 for action in &self.actions {
93 if let Action::Metadata(super::MetadataAction::Id(id)) = action {
94 return Some(*id);
95 }
96 }
97 None
98 }
99
100 /// Get the phase for this rule (defaults to 2).
101 pub fn phase(&self) -> u8 {
102 for action in &self.actions {
103 if let Action::Metadata(super::MetadataAction::Phase(phase)) = action {
104 return *phase;
105 }
106 }
107 2 // Default phase is 2 (request body)
108 }
109}