usiem/events/
webproxy.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#[derive(Serialize, Deserialize, Debug, Clone)]
9pub struct WebProxyEvent {
10    pub source_ip: SiemIp,
11    pub destination_ip: SiemIp,
12    pub destination_port: u16,
13    pub in_bytes: u32,
14    pub out_bytes: u32,
15    pub http_code: u32,
16    pub http_method: HttpMethod,
17    pub url: LogString,
18    pub domain: LogString,
19    /// Web protocol: http, https, ftp...Only UPPERCASE
20    pub protocol: WebProtocol,
21    pub user_name: LogString,
22    pub mime_type: LogString,
23    pub outcome: WebProxyOutcome,
24    /// Rule that routed/blocked the connection
25    pub rule_name: Option<LogString>,
26    /// Categorization of the traffic
27    pub rule_category: Option<WebProxyRuleCategory>,
28}
29impl WebProxyEvent {
30    pub fn source_ip(&self) -> &SiemIp {
31        &self.source_ip
32    }
33    pub fn destination_ip(&self) -> &SiemIp {
34        &self.destination_ip
35    }
36    pub fn protocol(&self) -> &WebProtocol {
37        &self.protocol
38    }
39    pub fn outcome(&self) -> &WebProxyOutcome {
40        &self.outcome
41    }
42    pub fn http_method(&self) -> &HttpMethod {
43        &self.http_method
44    }
45    pub fn user_name(&self) -> &str {
46        &self.user_name
47    }
48    pub fn mime_type(&self) -> &str {
49        &self.mime_type
50    }
51    pub fn url(&self) -> &str {
52        &self.url
53    }
54    pub fn domain(&self) -> &str {
55        &self.domain
56    }
57    pub fn rule_name(&self) -> &Option<LogString> {
58        &self.rule_name
59    }
60    pub fn rule_category(&self) -> &Option<WebProxyRuleCategory> {
61        &self.rule_category
62    }
63}
64
65#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
66pub enum WebProxyOutcome {
67    /// Connection was blocked
68    BLOCK,
69    /// Connection was allowed
70    ALLOW,
71    /// Unknow connection state.
72    UNKNOWN,
73}
74impl std::fmt::Display for WebProxyOutcome {
75    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
76        write!(f, "{:?}", self)
77        // or, alternatively:
78        // fmt::Debug::fmt(self, f)
79    }
80}
81
82/// Based on Bluecoat categories http://sitereview.bluecoat.com/#/category-descriptions
83#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
84pub enum WebProxyRuleCategory {
85    Abortion,
86    MatureContent,
87    Alcohol,
88    AlternativeSpirituality,
89    ArtCulture,
90    Auctions,
91    AudioVideoClips,
92    Trading,
93    Economy,
94    Charitable,
95    OnlineChat,
96    ChildPornography,
97    CloudInfrastructure,
98    CompromisedSites,
99    InformationSecurity,
100    ContentDeliveryNetworks,
101    ControlledSubstances,
102    Cryptocurrency,
103    DynamicDNSHost,
104    ECardInvitations,
105    Education,
106    Email,
107    EmailMarketing,
108    Entertainment,
109    FileStorage,
110    Finance,
111    ForKids,
112    Gambling,
113    Games,
114    Gore,
115    Government,
116    Hacking,
117    Health,
118    HumorJokes,
119    Informational,
120    InternetConnectedDevices,
121    InternetTelephony,
122    IntimateApparel,
123    JobSearch,
124    MaliciousOutboundDataBotnets,
125    MaliciousSources,
126    Marijuana,
127    MediaSharing,
128    Military,
129    PotentiallyAdult,
130    News,
131    Forums,
132    Nudity,
133    BusinessApplications,
134    OnlineMeetings,
135    P2P,
136    PersonalSites,
137    PersonalsDating,
138    Phishing,
139    CopyrightConcerns,
140    Placeholders,
141    PoliticalAdvocacy,
142    Pornography,
143    PotentiallyUnwantedSoftware,
144    ProxyAvoidance,
145    RadioAudioStreams,
146    RealEstate,
147    Reference,
148    Religion,
149    RemoteAccess,
150    Restaurants,
151    QuestionableLegality,
152    SearchEngines,
153    SexEducation,
154    SexualExpression,
155    Shopping,
156    SocialNetworking,
157    DailyLiving,
158    SoftwareDownloads,
159    Spam,
160    Sports,
161    Suspicious,
162    Technology,
163    Tobacco,
164    Translation,
165    Travel,
166    VideoStreams,
167    Uncategorized,
168    URLShorteners,
169    Vehicles,
170    Violence,
171    Weapons,
172    WebAds,
173    WebHosting,
174    WebInfrastructure,
175    Others(String),
176}
177
178impl std::fmt::Display for WebProxyRuleCategory {
179    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
180        write!(f, "{:?}", self)
181        // or, alternatively:
182        // fmt::Debug::fmt(self, f)
183    }
184}
185
186impl From<WebProxyEvent> for SiemLog {
187    fn from(val: WebProxyEvent) -> Self {
188        let mut log = SiemLog::new("", 0, "");
189        log.add_field(SOURCE_IP, SiemField::IP(val.source_ip));
190        log.add_field(DESTINATION_IP, SiemField::IP(val.destination_ip));
191        log.add_field(
192            DESTINATION_PORT,
193            SiemField::U64(val.destination_port as u64),
194        );
195        log.add_field(
196            EVENT_OUTCOME,
197            SiemField::Text(LogString::Owned(val.outcome.to_string())),
198        );
199        log.add_field(SOURCE_BYTES, SiemField::U64(val.out_bytes as u64));
200        log.add_field(DESTINATION_BYTES, SiemField::U64(val.in_bytes as u64));
201        log.add_field(
202            NETWORK_PROTOCOL,
203            SiemField::Text(LogString::Owned(val.protocol.to_string())),
204        );
205        log.add_field(
206            HTTP_RESPONSE_STATUS_CODE,
207            SiemField::U64(val.http_code as u64),
208        );
209        log.add_field(
210            HTTP_REQUEST_METHOD,
211            SiemField::Text(LogString::Owned(val.http_method.to_string())),
212        );
213        log.add_field(URL_FULL, SiemField::Text(val.url));
214        log.add_field(URL_DOMAIN, SiemField::Text(val.domain));
215        log.add_field(USER_NAME, SiemField::User(val.user_name.to_string()));
216        log.add_field(HTTP_RESPONSE_MIME_TYPE, SiemField::Text(val.mime_type));
217        if let Some(rule_category) = val.rule_category {
218            log.add_field(
219                RULE_CATEGORY,
220                SiemField::Text(LogString::Owned(rule_category.to_string())),
221            );
222        }
223        if let Some(rule_name) = val.rule_name {
224            log.add_field(
225                RULE_NAME,
226                SiemField::Text(LogString::Owned(rule_name.to_string())),
227            );
228        }
229        log
230    }
231}