sentinel_modsec/engine/
mod.rs1pub mod chain;
4pub mod intervention;
5pub mod phase;
6pub mod ruleset;
7pub mod scoring;
8pub mod transaction;
9
10pub use intervention::Intervention;
11pub use ruleset::{CompiledRuleset, Rules};
12pub use transaction::Transaction;
13
14use crate::error::Result;
15use std::sync::Arc;
16
17pub struct ModSecurity {
19 ruleset: Arc<CompiledRuleset>,
21 default_status: u16,
23}
24
25impl ModSecurity {
26 pub fn new(ruleset: CompiledRuleset) -> Self {
28 Self {
29 ruleset: Arc::new(ruleset),
30 default_status: 403,
31 }
32 }
33
34 pub fn from_file(path: &str) -> Result<Self> {
36 let ruleset = CompiledRuleset::from_file(path)?;
37 Ok(Self::new(ruleset))
38 }
39
40 pub fn from_string(rules: &str) -> Result<Self> {
42 let ruleset = CompiledRuleset::from_string(rules)?;
43 Ok(Self::new(ruleset))
44 }
45
46 pub fn set_default_status(&mut self, status: u16) {
48 self.default_status = status;
49 }
50
51 pub fn new_transaction(&self) -> Transaction {
53 Transaction::new(Arc::clone(&self.ruleset), self.default_status)
54 }
55
56 pub fn ruleset(&self) -> &CompiledRuleset {
58 &self.ruleset
59 }
60
61 pub fn rule_count(&self) -> usize {
63 self.ruleset.rule_count()
64 }
65}
66
67impl std::fmt::Debug for ModSecurity {
68 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69 f.debug_struct("ModSecurity")
70 .field("rule_count", &self.ruleset.rule_count())
71 .field("default_status", &self.default_status)
72 .finish()
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79
80 #[test]
81 fn test_modsec_from_string() {
82 let rules = r#"
83 SecRule REQUEST_URI "@contains /admin" "id:1,phase:1,deny"
84 "#;
85 let modsec = ModSecurity::from_string(rules).unwrap();
86 assert_eq!(modsec.rule_count(), 1);
87 }
88
89 #[test]
90 fn test_new_transaction() {
91 let rules = r#"
92 SecRule REQUEST_URI "@contains /admin" "id:1,phase:1,deny"
93 "#;
94 let modsec = ModSecurity::from_string(rules).unwrap();
95 let _tx = modsec.new_transaction();
96 }
97}