usiem/events/
auth.rs

1use crate::prelude::{types::LogString, SiemField, SiemIp, SiemLog};
2use serde::{Deserialize, Serialize};
3
4use super::field_dictionary::*;
5
6#[derive(Serialize, Deserialize, Debug, Clone)]
7pub struct AuthEvent {
8    /// Login type: local, remote, upgrade (change user)
9    pub login_type: AuthLoginType,
10    /// Login success or failed
11    pub outcome: LoginOutcome,
12    /// Host where the login happened
13    pub hostname: LogString,
14}
15
16impl AuthEvent {
17    pub fn login_type(&self) -> &AuthLoginType {
18        &self.login_type
19    }
20    pub fn outcome(&self) -> &LoginOutcome {
21        &self.outcome
22    }
23    pub fn hostname(&self) -> &str {
24        &self.hostname
25    }
26}
27
28#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
29pub enum AuthLoginType {
30    Local(LocalLogin),
31    Remote(RemoteLogin),
32    Upgrade(UpgradeLogin),
33    Validation(ValidationLogin),
34    Delegation(DelegationLogin),
35}
36
37#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
38pub enum LoginOutcome {
39    /// Login success
40    SUCCESS,
41    /// Login failed
42    FAIL,
43    /// Account locked out
44    LOCKOUT,
45    /// Pre authentication phase: trying to connect
46    ESTABLISH,
47}
48
49/// A user is login in locally, in front of the computer (or almost).
50#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
51pub struct LocalLogin {
52    /// User that logged in
53    pub user_name: LogString,
54    /// User domain
55    pub domain: LogString,
56}
57
58impl LocalLogin {
59    pub fn new<S>(user_name: S, domain: S) -> Self
60    where
61        S: Into<LogString>,
62    {
63        Self {
64            user_name: user_name.into(),
65            domain: domain.into(),
66        }
67    }
68}
69
70/// A user uses a Credential Vault like CyberArk to use an account
71#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
72pub struct DelegationLogin {
73    /// Original user name
74    pub source_user: LogString,
75    pub source_domain: LogString,
76    /// User to be logged as
77    pub destination_user: LogString,
78    /// Domain of the user to be logged as
79    pub destination_domain: LogString,
80}
81
82impl DelegationLogin {
83    pub fn new<S>(
84        source_user: S,
85        source_domain: S,
86        destination_user: S,
87        destination_domain: S,
88    ) -> Self
89    where
90        S: Into<LogString>,
91    {
92        Self {
93            source_user: source_user.into(),
94            source_domain: source_domain.into(),
95            destination_domain: destination_domain.into(),
96            destination_user: destination_user.into(),
97        }
98    }
99}
100
101/// Someone tries to login in the system from another computer.
102#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
103pub struct RemoteLogin {
104    /// User that logged in
105    pub user_name: LogString,
106    /// User domain
107    pub domain: LogString,
108    /// Ip or hostname of the remote location
109    pub source_address: LogString,
110}
111
112impl RemoteLogin {
113    pub fn new<S>(user_name: S, domain: S, source_address: S) -> Self
114    where
115        S: Into<LogString>,
116    {
117        Self {
118            user_name: user_name.into(),
119            domain: domain.into(),
120            source_address: source_address.into(),
121        }
122    }
123}
124
125/// A user changes into another account, like a "su" command in linux
126#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
127pub struct UpgradeLogin {
128    /// Original user name
129    pub source_user: LogString,
130    /// User to be logged as
131    pub destination_user: LogString,
132    /// Domain of the user to be logged as
133    pub destination_domain: LogString,
134}
135
136impl UpgradeLogin {
137    pub fn new<S>(source_user: S, destination_user: S, destination_domain: S) -> Self
138    where
139        S: Into<LogString>,
140    {
141        Self {
142            source_user: source_user.into(),
143            destination_domain: destination_domain.into(),
144            destination_user: destination_user.into(),
145        }
146    }
147}
148
149/// This does not imply a user login in the system, only validation of credentials. Like LoginType=3 in Windows.
150#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
151pub struct ValidationLogin {
152    /// User doing the login
153    pub user_name: LogString,
154    /// Origin og the connection
155    pub source_address: LogString,
156}
157
158impl ValidationLogin {
159    pub fn new<S>(user_name: S, source_address: S) -> Self
160    where
161        S: Into<LogString>,
162    {
163        Self {
164            user_name: user_name.into(),
165            source_address: source_address.into(),
166        }
167    }
168}
169
170impl std::fmt::Display for AuthLoginType {
171    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
172        write!(f, "{:?}", self)
173        // or, alternatively:
174        // fmt::Debug::fmt(self, f)
175    }
176}
177impl std::fmt::Display for LoginOutcome {
178    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
179        write!(f, "{:?}", self)
180        // or, alternatively:
181        // fmt::Debug::fmt(self, f)
182    }
183}
184
185impl From<AuthEvent> for SiemLog {
186    fn from(val: AuthEvent) -> Self {
187        let mut log = SiemLog::new("", 0, "");
188        log.add_field("host.hostname", SiemField::Text(val.hostname));
189        log.add_field(
190            EVENT_OUTCOME,
191            SiemField::Text(LogString::Owned(val.outcome.to_string())),
192        );
193        match val.login_type {
194            AuthLoginType::Local(evnt) => {
195                log.add_field(USER_NAME, SiemField::User(evnt.user_name.to_string()));
196                log.add_field(USER_DOMAIN, SiemField::Domain(evnt.domain.to_string()));
197            }
198            AuthLoginType::Remote(evnt) => {
199                log.add_field(USER_NAME, SiemField::User(evnt.user_name.to_string()));
200                log.add_field(USER_DOMAIN, SiemField::Domain(evnt.domain.to_string()));
201                if let Ok(ip) = SiemIp::from_ip_str(&evnt.source_address) {
202                    log.add_field(SOURCE_IP, SiemField::IP(ip));
203                };
204                log.add_field("source.address", SiemField::Text(evnt.source_address));
205            }
206            AuthLoginType::Upgrade(evnt) => {
207                log.add_field(
208                    USER_NAME,
209                    SiemField::User(evnt.destination_user.to_string()),
210                );
211                log.add_field(
212                    "source.user.name",
213                    SiemField::User(evnt.source_user.to_string()),
214                );
215                log.add_field(
216                    USER_DOMAIN,
217                    SiemField::Domain(evnt.destination_domain.to_string()),
218                );
219            }
220            AuthLoginType::Validation(evnt) => {
221                log.add_field(USER_NAME, SiemField::User(evnt.user_name.to_string()));
222                if let Ok(ip) = SiemIp::from_ip_str(&evnt.source_address) {
223                    log.add_field("source.ip", SiemField::IP(ip));
224                };
225                log.add_field("source.address", SiemField::Text(evnt.source_address));
226            }
227            AuthLoginType::Delegation(evnt) => {
228                log.add_field(
229                    USER_NAME,
230                    SiemField::User(evnt.destination_user.to_string()),
231                );
232                log.add_field(
233                    "source.user.name",
234                    SiemField::User(evnt.source_user.to_string()),
235                );
236                log.add_field(
237                    USER_DOMAIN,
238                    SiemField::Domain(evnt.destination_domain.to_string()),
239                );
240                log.add_field(
241                    "source.user.domain",
242                    SiemField::Domain(evnt.source_domain.to_string()),
243                );
244            }
245        };
246        log
247    }
248}