usiem/events/
webserver.rs

1use super::common::{HttpMethod, WebProtocol};
2use super::field_dictionary::*;
3use super::ip::SiemIp;
4use crate::prelude::types::LogString;
5use crate::prelude::{SiemField, SiemLog};
6use serde::{Deserialize, Serialize};
7
8/// A typical combined Log format has a source_ip, a user_id, a date, the http method,
9/// the path requested, the user agent and the size of the resource returned
10#[derive(Serialize, Deserialize, Debug, Clone)]
11pub struct WebServerEvent {
12    pub source_ip: SiemIp,
13    pub destination_ip: Option<SiemIp>, //Server IP
14    pub destination_port: u16,
15    pub in_bytes: u32,
16    pub out_bytes: u32,
17    pub http_code: u32,
18    pub duration: f32,
19    pub http_method: HttpMethod,
20    pub user_agent: LogString,
21    pub url_full: LogString,
22    pub url_domain: LogString,
23    pub url_path: LogString,
24    pub url_query: LogString,
25    pub url_extension: LogString,
26    pub protocol: WebProtocol,
27    pub user_name: LogString,
28    pub mime_type: LogString,
29    pub outcome: WebServerOutcome,
30}
31impl WebServerEvent {
32    pub fn source_ip(&self) -> &SiemIp {
33        &self.source_ip
34    }
35    pub fn destination_ip(&self) -> &Option<SiemIp> {
36        &self.destination_ip
37    }
38    pub fn destination_port(&self) -> u16 {
39        self.destination_port
40    }
41    pub fn in_bytes(&self) -> u32 {
42        self.in_bytes
43    }
44    pub fn out_bytes(&self) -> u32 {
45        self.out_bytes
46    }
47    pub fn http_code(&self) -> u32 {
48        self.http_code
49    }
50    pub fn duration(&self) -> f32 {
51        self.duration
52    }
53    pub fn protocol(&self) -> &WebProtocol {
54        &self.protocol
55    }
56    pub fn outcome(&self) -> &WebServerOutcome {
57        &self.outcome
58    }
59    pub fn http_method(&self) -> &HttpMethod {
60        &self.http_method
61    }
62    pub fn user_name(&self) -> &str {
63        &self.user_name
64    }
65    pub fn mime_type(&self) -> &str {
66        &self.mime_type
67    }
68    pub fn url_full(&self) -> &str {
69        &self.url_full
70    }
71    pub fn url_domain(&self) -> &str {
72        &self.url_domain
73    }
74    pub fn url_path(&self) -> &str {
75        &self.url_path
76    }
77    pub fn url_query(&self) -> &str {
78        &self.url_query
79    }
80    pub fn url_extension(&self) -> &str {
81        &self.url_extension
82    }
83    pub fn user_agent(&self) -> &str {
84        &self.user_agent
85    }
86}
87
88#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
89pub enum WebServerOutcome {
90    /// Connection was blocked
91    BLOCK,
92    /// Connection was allowed
93    ALLOW,
94    /// Unknow connection state.
95    UNKNOWN,
96}
97impl std::fmt::Display for WebServerOutcome {
98    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
99        write!(f, "{:?}", self)
100        // or, alternatively:
101        // fmt::Debug::fmt(self, f)
102    }
103}
104
105impl From<WebServerEvent> for SiemLog {
106    fn from(val: WebServerEvent) -> Self {
107        let mut log = SiemLog::new("", 0, "");
108        log.add_field(SOURCE_IP, SiemField::IP(val.source_ip));
109        if let Some(ip) = val.destination_ip {
110            log.add_field(DESTINATION_IP, SiemField::IP(ip));
111        };
112
113        log.add_field(
114            DESTINATION_PORT,
115            SiemField::U64(val.destination_port as u64),
116        );
117        log.add_field(
118            EVENT_OUTCOME,
119            SiemField::Text(LogString::Owned(val.outcome.to_string())),
120        );
121        log.add_field(SOURCE_BYTES, SiemField::U64(val.out_bytes as u64));
122        log.add_field(DESTINATION_BYTES, SiemField::U64(val.in_bytes as u64));
123        log.add_field(
124            NETWORK_PROTOCOL,
125            SiemField::Text(LogString::Owned(val.protocol.to_string())),
126        );
127        log.add_field(
128            HTTP_RESPONSE_STATUS_CODE,
129            SiemField::U64(val.http_code as u64),
130        );
131        log.add_field(
132            HTTP_REQUEST_METHOD,
133            SiemField::Text(LogString::Owned(val.http_method.to_string())),
134        );
135        log.add_field(URL_FULL, SiemField::Text(val.url_full));
136        log.add_field(URL_DOMAIN, SiemField::Text(val.url_domain));
137        log.add_field(URL_PATH, SiemField::Text(val.url_path));
138        log.add_field(URL_QUERY, SiemField::Text(val.url_query));
139        log.add_field("url.extension", SiemField::Text(val.url_extension));
140        log.add_field(USER_NAME, SiemField::User(val.user_name.to_string()));
141        log.add_field(HTTP_RESPONSE_MIME_TYPE, SiemField::Text(val.mime_type));
142        log.add_field(NETWORK_DURATION, SiemField::F64(val.duration as f64));
143        log.add_field("user_agent.original", SiemField::Text(val.user_agent));
144        log
145    }
146}