usiem/components/dataset/
rules.rs1use crate::prelude::rule::SiemRule;
2use crate::prelude::types::LogString;
3use crossbeam_channel::Sender;
4use serde::Serialize;
5use std::collections::BTreeMap;
6use std::sync::Arc;
7use std::time::Duration;
8
9#[derive(Serialize, Debug)]
10pub enum UpdateRules {
11 Add(SiemRule),
12 Remove(LogString),
13 Replace(RulesDataset),
14}
15
16#[derive(Debug, Clone)]
17pub struct CorrelationRulesDataset {
18 dataset: Arc<RulesDataset>,
19 comm: Sender<UpdateRules>,
20}
21impl CorrelationRulesDataset {
22 pub fn new(dataset: Arc<RulesDataset>, comm: Sender<UpdateRules>) -> Self {
23 Self { dataset, comm }
24 }
25 pub fn insert(&self, rule: SiemRule) {
26 let _ = self.comm.send(UpdateRules::Add(rule));
27 }
28 pub fn insert_timeout(&self, rule: SiemRule, timeout: Duration) -> Result<(), SiemRule> {
29 let init = std::time::Instant::now();
30 let mut rule = rule;
31 loop {
32 rule = match self.comm.try_send(UpdateRules::Add(rule)) {
33 Ok(_) => return Ok(()),
34 Err(e) => match e {
35 crossbeam_channel::TrySendError::Full(r) => extract_rule_from_update(r),
36 crossbeam_channel::TrySendError::Disconnected(r) => extract_rule_from_update(r),
37 },
38 };
39 let now = std::time::Instant::now();
40 if now > init + timeout {
41 return Err(rule);
42 }
43 }
44 }
45 pub fn try_insert(&self, rule: SiemRule) -> Result<(), SiemRule> {
46 match self.comm.try_send(UpdateRules::Add(rule)) {
47 Ok(_) => Ok(()),
48 Err(e) => match e {
49 crossbeam_channel::TrySendError::Full(r) => Err(extract_rule_from_update(r)),
50 crossbeam_channel::TrySendError::Disconnected(r) => {
51 Err(extract_rule_from_update(r))
52 }
53 },
54 }
55 }
56 pub fn get(&self, id: &LogString) -> Option<&SiemRule> {
57 self.dataset.get(id)
59 }
60}
61#[derive(Serialize, Debug, Default)]
62pub struct RulesDataset {
63 rules: BTreeMap<LogString, SiemRule>,
64}
65
66impl RulesDataset {
67 pub fn new() -> Self {
68 Self::default()
69 }
70 pub fn insert(&mut self, rule: SiemRule) {
71 self.rules.insert(rule.name.clone(), rule);
72 }
73 pub fn get(&self, id: &LogString) -> Option<&SiemRule> {
74 self.rules.get(id)
75 }
76}
77
78fn extract_rule_from_update(update: UpdateRules) -> SiemRule {
79 match update {
80 UpdateRules::Add(r) => r,
81 UpdateRules::Remove(_) => unreachable!(),
82 UpdateRules::Replace(_) => unreachable!(),
83 }
84}