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 pub login_type: AuthLoginType,
10 pub outcome: LoginOutcome,
12 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 SUCCESS,
41 FAIL,
43 LOCKOUT,
45 ESTABLISH,
47}
48
49#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
51pub struct LocalLogin {
52 pub user_name: LogString,
54 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#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
72pub struct DelegationLogin {
73 pub source_user: LogString,
75 pub source_domain: LogString,
76 pub destination_user: LogString,
78 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#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
103pub struct RemoteLogin {
104 pub user_name: LogString,
106 pub domain: LogString,
108 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#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
127pub struct UpgradeLogin {
128 pub source_user: LogString,
130 pub destination_user: LogString,
132 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#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
151pub struct ValidationLogin {
152 pub user_name: LogString,
154 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 }
176}
177impl std::fmt::Display for LoginOutcome {
178 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
179 write!(f, "{:?}", self)
180 }
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}