use crate::prelude::{types::LogString, SiemField, SiemIp, SiemLog};
use serde::{Deserialize, Serialize};
use super::field_dictionary::*;
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct AuthEvent {
pub login_type: AuthLoginType,
pub outcome: LoginOutcome,
pub hostname: LogString,
}
impl AuthEvent {
pub fn login_type(&self) -> &AuthLoginType {
&self.login_type
}
pub fn outcome(&self) -> &LoginOutcome {
&self.outcome
}
pub fn hostname(&self) -> &str {
&self.hostname
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
pub enum AuthLoginType {
Local(LocalLogin),
Remote(RemoteLogin),
Upgrade(UpgradeLogin),
Validation(ValidationLogin),
Delegation(DelegationLogin),
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
pub enum LoginOutcome {
SUCCESS,
FAIL,
LOCKOUT,
ESTABLISH,
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
pub struct LocalLogin {
pub user_name: LogString,
pub domain: LogString,
}
impl LocalLogin {
pub fn new<S>(user_name: S, domain: S) -> Self
where
S: Into<LogString>,
{
Self {
user_name: user_name.into(),
domain: domain.into(),
}
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
pub struct DelegationLogin {
pub source_user: LogString,
pub source_domain: LogString,
pub destination_user: LogString,
pub destination_domain: LogString,
}
impl DelegationLogin {
pub fn new<S>(
source_user: S,
source_domain: S,
destination_user: S,
destination_domain: S,
) -> Self
where
S: Into<LogString>,
{
Self {
source_user: source_user.into(),
source_domain: source_domain.into(),
destination_domain: destination_domain.into(),
destination_user: destination_user.into(),
}
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
pub struct RemoteLogin {
pub user_name: LogString,
pub domain: LogString,
pub source_address: LogString,
}
impl RemoteLogin {
pub fn new<S>(user_name: S, domain: S, source_address: S) -> Self
where
S: Into<LogString>,
{
Self {
user_name: user_name.into(),
domain: domain.into(),
source_address: source_address.into(),
}
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
pub struct UpgradeLogin {
pub source_user: LogString,
pub destination_user: LogString,
pub destination_domain: LogString,
}
impl UpgradeLogin {
pub fn new<S>(source_user: S, destination_user: S, destination_domain: S) -> Self
where
S: Into<LogString>,
{
Self {
source_user: source_user.into(),
destination_domain: destination_domain.into(),
destination_user: destination_user.into(),
}
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
pub struct ValidationLogin {
pub user_name: LogString,
pub source_address: LogString,
}
impl ValidationLogin {
pub fn new<S>(user_name: S, source_address: S) -> Self
where
S: Into<LogString>,
{
Self {
user_name: user_name.into(),
source_address: source_address.into(),
}
}
}
impl std::fmt::Display for AuthLoginType {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}
impl std::fmt::Display for LoginOutcome {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}
impl From<AuthEvent> for SiemLog {
fn from(val: AuthEvent) -> Self {
let mut log = SiemLog::new("", 0, "");
log.add_field("host.hostname", SiemField::Text(val.hostname));
log.add_field(
EVENT_OUTCOME,
SiemField::Text(LogString::Owned(val.outcome.to_string())),
);
match val.login_type {
AuthLoginType::Local(evnt) => {
log.add_field(USER_NAME, SiemField::User(evnt.user_name.to_string()));
log.add_field(USER_DOMAIN, SiemField::Domain(evnt.domain.to_string()));
}
AuthLoginType::Remote(evnt) => {
log.add_field(USER_NAME, SiemField::User(evnt.user_name.to_string()));
log.add_field(USER_DOMAIN, SiemField::Domain(evnt.domain.to_string()));
if let Ok(ip) = SiemIp::from_ip_str(&evnt.source_address) {
log.add_field(SOURCE_IP, SiemField::IP(ip));
};
log.add_field("source.address", SiemField::Text(evnt.source_address));
}
AuthLoginType::Upgrade(evnt) => {
log.add_field(
USER_NAME,
SiemField::User(evnt.destination_user.to_string()),
);
log.add_field(
"source.user.name",
SiemField::User(evnt.source_user.to_string()),
);
log.add_field(
USER_DOMAIN,
SiemField::Domain(evnt.destination_domain.to_string()),
);
}
AuthLoginType::Validation(evnt) => {
log.add_field(USER_NAME, SiemField::User(evnt.user_name.to_string()));
if let Ok(ip) = SiemIp::from_ip_str(&evnt.source_address) {
log.add_field("source.ip", SiemField::IP(ip));
};
log.add_field("source.address", SiemField::Text(evnt.source_address));
}
AuthLoginType::Delegation(evnt) => {
log.add_field(
USER_NAME,
SiemField::User(evnt.destination_user.to_string()),
);
log.add_field(
"source.user.name",
SiemField::User(evnt.source_user.to_string()),
);
log.add_field(
USER_DOMAIN,
SiemField::Domain(evnt.destination_domain.to_string()),
);
log.add_field(
"source.user.domain",
SiemField::Domain(evnt.source_domain.to_string()),
);
}
};
log
}
}