From 2313e90e32f67d8ec86f83b10c537b9785bbfacd Mon Sep 17 00:00:00 2001 From: Vincent Ruello <5345986+vruello@users.noreply.github.com> Date: Tue, 30 Apr 2024 10:22:05 +0200 Subject: [PATCH] Add Nxlog format (#124) --- CHANGELOG.md | 1 + Cargo.lock | 1 + cli/src/skell.rs | 4 + common/src/models/config.rs | 10 +- common/src/models/export.rs | 11 +- common/src/subscription.rs | 2 + doc/formats.md | 51 ++- server/Cargo.toml | 1 + server/src/formats/mod.rs | 3 +- server/src/formats/nxlog.rs | 708 ++++++++++++++++++++++++++++++++++++ server/src/output.rs | 5 +- 11 files changed, 781 insertions(+), 16 deletions(-) create mode 100644 server/src/formats/nxlog.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index f28b705..c17ced7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add `locale` and `data_locale` subscriptions parameters - Add support for Proxy Protocol to allow openwec to be used behind a layer 4 load balancer whilst preserving the client IP address and port. +- Add Nxlog format (#124) ### Changed diff --git a/Cargo.lock b/Cargo.lock index 0917976..42af846 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2049,6 +2049,7 @@ dependencies = [ "serde_json", "sha1", "socket2 0.5.7", + "strum", "thiserror", "tokio", "tokio-rustls", diff --git a/cli/src/skell.rs b/cli/src/skell.rs index 555e269..00a81ec 100644 --- a/cli/src/skell.rs +++ b/cli/src/skell.rs @@ -136,6 +136,10 @@ fn get_outputs() -> String { # Outputs # +# For each output, you must configure a driver and a format. +# The format can be one of: "Raw", "JsonRaw", "Json", "Nxlog" +# The driver can be one of: "Files", "Kafka", "Tcp", "Redis", "UnixDatagram" + # Configure a Files output # [[outputs]] # driver = "Files" diff --git a/common/src/models/config.rs b/common/src/models/config.rs index c0ae88d..842ddba 100644 --- a/common/src/models/config.rs +++ b/common/src/models/config.rs @@ -137,6 +137,7 @@ enum SubscriptionOutputFormat { Json, Raw, RawJson, + Nxlog } impl From for crate::subscription::SubscriptionOutputFormat { @@ -144,9 +145,8 @@ impl From for crate::subscription::SubscriptionOutputF match value { SubscriptionOutputFormat::Json => crate::subscription::SubscriptionOutputFormat::Json, SubscriptionOutputFormat::Raw => crate::subscription::SubscriptionOutputFormat::Raw, - SubscriptionOutputFormat::RawJson => { - crate::subscription::SubscriptionOutputFormat::RawJson - } + SubscriptionOutputFormat::RawJson => crate::subscription::SubscriptionOutputFormat::RawJson, + SubscriptionOutputFormat::Nxlog => crate::subscription::SubscriptionOutputFormat::Nxlog } } } @@ -382,7 +382,7 @@ port = 8080 ## Redis output [[outputs]] driver = "Redis" -format = "Json" +format = "Nxlog" enabled = false [outputs.config] @@ -456,7 +456,7 @@ path = "/tmp/openwec.socket" true, ), crate::subscription::SubscriptionOutput::new( - crate::subscription::SubscriptionOutputFormat::Json, + crate::subscription::SubscriptionOutputFormat::Nxlog, crate::subscription::SubscriptionOutputDriver::Redis( crate::subscription::RedisConfiguration::new( "localhost".to_string(), diff --git a/common/src/models/export.rs b/common/src/models/export.rs index f1cf29f..1fa98b6 100644 --- a/common/src/models/export.rs +++ b/common/src/models/export.rs @@ -206,6 +206,7 @@ mod v1 { Json, Raw, RawJson, + Nxlog, } impl From for crate::subscription::SubscriptionOutputFormat { @@ -215,9 +216,8 @@ mod v1 { crate::subscription::SubscriptionOutputFormat::Json } SubscriptionOutputFormat::Raw => crate::subscription::SubscriptionOutputFormat::Raw, - SubscriptionOutputFormat::RawJson => { - crate::subscription::SubscriptionOutputFormat::RawJson - } + SubscriptionOutputFormat::RawJson => crate::subscription::SubscriptionOutputFormat::RawJson, + SubscriptionOutputFormat::Nxlog => crate::subscription::SubscriptionOutputFormat::Nxlog, } } } @@ -229,9 +229,8 @@ mod v1 { SubscriptionOutputFormat::Json } crate::subscription::SubscriptionOutputFormat::Raw => SubscriptionOutputFormat::Raw, - crate::subscription::SubscriptionOutputFormat::RawJson => { - SubscriptionOutputFormat::RawJson - } + crate::subscription::SubscriptionOutputFormat::RawJson => SubscriptionOutputFormat::RawJson, + crate::subscription::SubscriptionOutputFormat::Nxlog => SubscriptionOutputFormat::Nxlog, } } } diff --git a/common/src/subscription.rs b/common/src/subscription.rs index b3fd1cd..74ef61e 100644 --- a/common/src/subscription.rs +++ b/common/src/subscription.rs @@ -217,6 +217,7 @@ pub enum SubscriptionOutputFormat { Json, Raw, RawJson, + Nxlog, } impl SubscriptionOutputFormat { @@ -227,6 +228,7 @@ impl SubscriptionOutputFormat { SubscriptionOutputFormat::Raw => false, SubscriptionOutputFormat::RawJson => false, SubscriptionOutputFormat::Json => true, + SubscriptionOutputFormat::Nxlog => true, } } } diff --git a/doc/formats.md b/doc/formats.md index af59c0c..9d877d0 100644 --- a/doc/formats.md +++ b/doc/formats.md @@ -245,11 +245,58 @@ processing_error_data := { } ``` +## Nxlog format + +This format mimics the output of the `im_msvistalog` module of Nxlog (see https://docs.nxlog.co/refman/current/im/msvistalog.html). + +Fields are documentated here: +- https://docs.nxlog.co/refman/current/im/msvistalog.html#fields +- https://docs.nxlog.co/refman/current/im/msvistalog_providers.html + +There are some differencies between the OpenWEC's Nxlog format and the original format: +- Some fields are not present in OpenWEC's Nxlog format: `AccountName`, `AccountType`, `Domain`, `SourceModuleName`, `SourceModuleType`. +- Some fields are only present if OpenWEC's subscription content format is set to `RenderedText`: `Category`, `Message`, `Opcode`. +- Dates are formatted using RFC3389 format (instead of "Y-m-d H:M:S") +- A field named `OpenWEC` is added with the following format: +```json +openwec_data := { + /* IP Address of the Windows client */ + "IpAddress": string, + /* Time when the event was received by OpenWEC */ + "TimeReceived": date, + /* Principal of the Windows client */ + "Principal": string, + /* OpenWEC node that received the event. + Only present if server.node_name configuration setting is set */ + "Node": string, + "Subscription": { + "Name": string, + "Version": string, + "Uuid": string, + "Uri": string, + /* Only if revision is set for this subscription */ + "ServerRevision": string, + "ClientRevision": string + }, + /* Only in case of error during event parsing or serializing */ + "Error": { + "OriginalContent": string, + "Type": string, + "Message": string + } +} +``` + + ## How to add a new format ? -- Create a new dedicated module in `server::formats` with a structure that implements `OutputFormat` - Add a new variant to `common::subscription::SubscriptionOutputFormat` -- Fix all the compiler errors about missing variant in matches :-) - Adapt import/export format in `common::models::export` (version don't need to be changed if only new variants are added) - Adapt config format in `common::models::config` + +- Create a new dedicated module in `server::formats` with a structure that implements `OutputFormat` + +- Fix all the compiler errors about missing variant in matches :-) +- Add the new format in `cli::skell` + - Add documentation in `doc/formats.md` \ No newline at end of file diff --git a/server/Cargo.toml b/server/Cargo.toml index 8596e8a..790e940 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -50,3 +50,4 @@ socket2 = "0.5.6" http-body-util = "0.1" ppp = "2.2.0" tokio-rustls = "0.26.0" +strum = { version = "0.26.1", features = ["derive"] } diff --git a/server/src/formats/mod.rs b/server/src/formats/mod.rs index cc875cf..b9583f7 100644 --- a/server/src/formats/mod.rs +++ b/server/src/formats/mod.rs @@ -1,3 +1,4 @@ pub mod json; pub mod raw; -pub mod raw_json; \ No newline at end of file +pub mod raw_json; +pub mod nxlog; \ No newline at end of file diff --git a/server/src/formats/nxlog.rs b/server/src/formats/nxlog.rs new file mode 100644 index 0000000..9c3a9a5 --- /dev/null +++ b/server/src/formats/nxlog.rs @@ -0,0 +1,708 @@ +use std::{collections::HashMap, fmt::Debug, sync::Arc}; + +use log::warn; +use serde::Serialize; +use strum::Display; + +use crate::{ + event::{EventData, EventMetadata}, + output::OutputFormat, +}; + +// Contants taken from https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.tracing.eventkeywords?view=net-8.0 +const AUDIT_SUCCESS_MASK: i64 = 9007199254740992; +const AUDIT_FAILURE_MASK: i64 = 4503599627370496; + +pub struct NxlogFormat; + +impl OutputFormat for NxlogFormat { + fn format(&self, metadata: &EventMetadata, data: &EventData) -> Option> { + if let Some(event) = data.event() { + let json_event = NxlogEvent::new(event.clone(), metadata); + match serde_json::to_string(&json_event) { + Ok(str) => Some(Arc::new(str)), + Err(e) => { + warn!( + "Failed to serialize event in JSON with NxlogFormat: {:?}. Event was: {:?}. Metadata was: {:?}. Raw event was: {:?}.", + e, event, metadata, data.raw() + ); + None + } + } + } else { + warn!("Failed to retrieve parsed event"); + None + } + } +} + +#[derive(Debug, Serialize)] +struct EventDataType { + #[serde(flatten, skip_serializing_if = "HashMap::is_empty")] + named_data: HashMap, + #[serde(rename = "Data", skip_serializing_if = "Vec::is_empty")] + unamed_data: Vec, + #[serde(rename = "Binary", skip_serializing_if = "Option::is_none")] + binary: Option, +} + +impl From for EventDataType { + fn from(value: crate::event::EventDataType) -> Self { + Self { + named_data: value.named_data, + unamed_data: value.unamed_data, + binary: value.binary, + } + } +} + +#[derive(Debug, Serialize)] +struct DebugDataType { + #[serde(rename = "SequenceNumber", skip_serializing_if = "Option::is_none")] + sequence_number: Option, + #[serde(rename = "FlagsName", skip_serializing_if = "Option::is_none")] + flags_name: Option, + #[serde(rename = "LevelName", skip_serializing_if = "Option::is_none")] + level_name: Option, + #[serde(rename = "Component")] + component: String, + #[serde(rename = "SubComponent", skip_serializing_if = "Option::is_none")] + sub_component: Option, + #[serde(rename = "FileLine", skip_serializing_if = "Option::is_none")] + file_line: Option, + #[serde(rename = "Function", skip_serializing_if = "Option::is_none")] + function: Option, + #[serde(rename = "Message")] + message: String, +} + +impl From for DebugDataType { + fn from(value: crate::event::DebugDataType) -> Self { + Self { + sequence_number: value.sequence_number, + flags_name: value.flags_name, + level_name: value.level_name, + component: value.component, + sub_component: value.sub_component, + file_line: value.file_line, + function: value.function, + message: value.message, + } + } +} + +#[derive(Debug, Serialize)] +struct ProcessingErrorDataType { + #[serde(rename = "ErrorCode")] + error_code: u32, + #[serde(rename = "DataItemName")] + data_item_name: String, + #[serde(rename = "EventPayload")] + event_payload: String, +} + +impl From for ProcessingErrorDataType { + fn from(value: crate::event::ProcessingErrorDataType) -> Self { + Self { + error_code: value.error_code, + data_item_name: value.data_item_name, + event_payload: value.event_payload, + } + } +} + +#[derive(Serialize, Debug)] +struct UserDataType { + #[serde(rename = "UserData")] + payload: String, +} + +impl From for UserDataType { + fn from(value: String) -> Self { + Self { payload: value } + } +} + +#[derive(Serialize, Debug)] +struct BinaryEventData { + #[serde(rename = "BinaryEventData")] + payload: String, +} + +impl From for BinaryEventData { + fn from(value: String) -> Self { + Self { payload: value } + } +} + +#[derive(Debug, Serialize)] +#[serde(untagged)] +enum DataType { + EventData(EventDataType), + UserData(UserDataType), + DebugData(DebugDataType), + ProcessingErrorData(ProcessingErrorDataType), + BinaryEventData(BinaryEventData), + Unknown, +} + +impl DataType { + fn is_unknown(&self) -> bool { + matches!(self, DataType::Unknown) + } +} + +impl From for DataType { + fn from(value: crate::event::DataType) -> Self { + match value { + crate::event::DataType::EventData(t) => DataType::EventData(t.into()), + crate::event::DataType::UserData(t) => DataType::UserData(t.into()), + crate::event::DataType::DebugData(t) => DataType::DebugData(t.into()), + crate::event::DataType::ProcessingErrorData(t) => { + DataType::ProcessingErrorData(t.into()) + } + crate::event::DataType::BinaryEventData(t) => DataType::BinaryEventData(t.into()), + crate::event::DataType::Unknown => DataType::Unknown, + } + } +} + +#[derive(Serialize, Debug)] +#[serde(tag = "Type")] +enum ErrorType { + /// Initial XML parsing failed but Raw content could be recovered + RawContentRecovered { + #[serde(rename = "Message")] + message: String, + }, + /// Initial XML parsing failed and recovering failed again + FailedToRecoverRawContent { + #[serde(rename = "Message")] + message: String, + }, + /// Initial XML parsing failed and no recovering strategy was usable + Unrecoverable { + #[serde(rename = "Message")] + message: String, + }, + /// Failed to feed event from parsed XML document + FailedToFeedEvent { + #[serde(rename = "Message")] + message: String, + }, + Unknown, +} + +impl From for ErrorType { + fn from(value: crate::event::ErrorType) -> Self { + match value { + crate::event::ErrorType::RawContentRecovered(message) => { + ErrorType::RawContentRecovered { message } + } + crate::event::ErrorType::FailedToRecoverRawContent(message) => { + ErrorType::FailedToRecoverRawContent { message } + } + crate::event::ErrorType::Unrecoverable(message) => ErrorType::Unrecoverable { message }, + crate::event::ErrorType::FailedToFeedEvent(message) => { + ErrorType::FailedToFeedEvent { message } + } + crate::event::ErrorType::Unknown => ErrorType::Unknown, + } + } +} + +#[derive(Debug, Serialize)] +struct ErrorInfo { + #[serde(rename = "OriginalContent")] + original_content: String, + #[serde(flatten)] + error_type: ErrorType, +} + +impl From for ErrorInfo { + fn from(value: crate::event::ErrorInfo) -> Self { + Self { + original_content: value.original_content, + error_type: value.error_type.into(), + } + } +} + +#[derive(Debug, Serialize)] +struct NxlogEvent { + #[serde(flatten, skip_serializing_if = "Option::is_none")] + system: Option, + #[serde(flatten, skip_serializing_if = "DataType::is_unknown")] + data: DataType, + #[serde(flatten, skip_serializing_if = "Option::is_none")] + rendering_info: Option, + #[serde(rename = "OpenWEC")] + additional: Additional, + #[serde(rename = "EventReceivedTime")] + event_received_time: String, +} + +impl NxlogEvent { + pub fn new(event: crate::event::Event, metadata: &EventMetadata) -> Self { + Self { + system: event.system.map(Into::into), + data: event.data.into(), + rendering_info: event.rendering_info.map(Into::into), + additional: Additional::new(event.additional, metadata), + event_received_time: metadata.time_received().to_rfc3339(), + } + } +} + +#[derive(Debug, Serialize)] +struct Additional { + #[serde(rename = "IpAddress")] + addr: String, + #[serde(rename = "TimeReceived")] + time_received: String, + #[serde(rename = "Principal")] + principal: String, + #[serde(rename = "Subscription")] + subscription: SubscriptionType, + #[serde(rename = "Node", skip_serializing_if = "Option::is_none")] + node: Option, + #[serde(rename = "Error", skip_serializing_if = "Option::is_none")] + error: Option, +} + +impl Additional { + pub fn new(additional: crate::event::Additional, metadata: &EventMetadata) -> Self { + Self { + addr: metadata.addr().ip().to_string(), + principal: metadata.principal().to_owned(), // TODO : change to something that works for TLS as well (modify db and output) + node: metadata.node_name().cloned(), + time_received: metadata.time_received().to_rfc3339(), + subscription: SubscriptionType { + uuid: metadata.subscription_uuid().to_owned(), + version: metadata.subscription_version().to_owned(), + name: metadata.subscription_name().to_owned(), + uri: metadata.subscription_uri().cloned(), + client_revision: metadata.subscription_client_revision().cloned(), + server_revision: metadata.subscription_server_revision().cloned(), + }, + error: additional.error.map(Into::into), + } + } +} + +#[derive(Debug, Serialize, Clone)] +struct SubscriptionType { + #[serde(rename = "Uuid")] + uuid: String, + #[serde(rename = "Version")] + version: String, + #[serde(rename = "Name")] + name: String, + #[serde(rename = "Uri", skip_serializing_if = "Option::is_none")] + uri: Option, + #[serde(rename = "ClientRevision", skip_serializing_if = "Option::is_none")] + client_revision: Option, + #[serde(rename = "ServerRevision", skip_serializing_if = "Option::is_none")] + server_revision: Option, +} + +#[derive(Debug, Serialize, Clone)] +struct Provider { + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(rename = "SourceName")] + name: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(rename = "ProviderGuid")] + guid: Option, +} + +impl From for Provider { + fn from(value: crate::event::Provider) -> Self { + Self { + name: value.name, + guid: value.guid.map(|x| x.to_uppercase()), + } + } +} + +#[derive(Debug, Serialize, Clone)] +struct Correlation { + #[serde(rename = "ActivityID", skip_serializing_if = "Option::is_none")] + activity_id: Option, + #[serde(rename = "RelatedActivityID", skip_serializing_if = "Option::is_none")] + related_activity_id: Option, +} + +impl From for Correlation { + fn from(value: crate::event::Correlation) -> Self { + Self { + activity_id: value.activity_id.map(|x| x.to_uppercase()), + related_activity_id: value.related_activity_id.map(|x| x.to_uppercase()), + } + } +} + +#[derive(Debug, Serialize, Clone)] +struct Execution { + #[serde(rename = "ProcessID")] + process_id: u32, + #[serde(rename = "ThreadID")] + thread_id: u32, +} + +impl From for Execution { + fn from(value: crate::event::Execution) -> Self { + Self { + process_id: value.process_id, + thread_id: value.thread_id, + } + } +} + +#[derive(Debug, Serialize, Clone)] +struct System { + #[serde(flatten)] + provider: Provider, + #[serde(rename = "EventID")] + event_id: u32, + #[serde(rename = "Version", skip_serializing_if = "Option::is_none")] + version: Option, + #[serde(rename = "Task", skip_serializing_if = "Option::is_none")] + task: Option, + #[serde(rename = "OpcodeValue", skip_serializing_if = "Option::is_none")] + opcode: Option, + #[serde(rename = "Keywords", skip_serializing_if = "Option::is_none")] + keywords: Option, + #[serde(rename = "EventTime", skip_serializing_if = "Option::is_none")] + time_created: Option, + #[serde(rename = "RecordNumber", skip_serializing_if = "Option::is_none")] + event_record_id: Option, + #[serde(flatten, skip_serializing_if = "Option::is_none")] + correlation: Option, + #[serde(flatten, skip_serializing_if = "Option::is_none")] + execution: Option, + #[serde(rename = "Channel", skip_serializing_if = "Option::is_none")] + channel: Option, + #[serde(rename = "Hostname")] + computer: String, + #[serde(rename = "UserID", skip_serializing_if = "Option::is_none")] + user_id: Option, + #[serde(rename = "EventType", skip_serializing_if = "Option::is_none")] + event_type: Option, + #[serde(rename = "Severity", skip_serializing_if = "Option::is_none")] + severity: Option, + #[serde(rename = "SeverityValue", skip_serializing_if = "Option::is_none")] + severity_value: Option, +} + +impl From for System { + fn from(value: crate::event::System) -> Self { + let keywords_number = parse_keywords(value.keywords.as_ref()); + let event_type = get_event_type(value.channel.as_ref(), value.level, keywords_number); + let severity: Option = event_type.clone().map(|e| e.into()); + Self { + event_type: event_type.map(|e| e.to_string()), + provider: value.provider.into(), + event_id: value.event_id, + version: value.version, + task: value.task, + opcode: value.opcode, + keywords: keywords_number, + time_created: value.time_created, + event_record_id: value.event_record_id, + correlation: value.correlation.map(Into::into), + execution: value.execution.map(Into::into), + channel: value.channel, + computer: value.computer, + user_id: value.user_id, + severity: severity.as_ref().map(|s| s.to_string()), + severity_value: severity.map(|s| s as u8), + } + } +} + +fn parse_keywords(keywords_opt: Option<&String>) -> Option { + if let Some(keywords) = keywords_opt { + if let Some(keywords_without_prefix) = keywords.strip_prefix("0x") { + // We need to convert u64 to i64 because for some reason + // i64::from_str_radix can't decode negative values. + match u64::from_str_radix(keywords_without_prefix, 16) { + Ok(res) => Some(res as i64), + Err(_) => None, + } + } else { + None + } + } else { + None + } +} + +#[derive(Debug, Display, Clone)] +enum EventType { + #[strum(to_string = "CRITICAL")] + Critical, + #[strum(to_string = "ERROR")] + Error, + #[strum(to_string = "WARNING")] + Warning, + #[strum(to_string = "INFO")] + Info, + #[strum(to_string = "VERBOSE")] + Verbose, + #[strum(to_string = "AUDIT_SUCCESS")] + AuditSuccess, + #[strum(to_string = "AUDIT_FAILURE")] + AuditFailure, +} + +fn get_event_type( + channel_opt: Option<&String>, + level_opt: Option, + keywords_number: Option, +) -> Option { + // Read https://eventlogxp.com/blog/windows-event-level-keywords-or-type/ + // https://docs.nxlog.co/refman/current/im/msvistalog.html#eventtype + match channel_opt { + Some(channel) if channel == "Security" => { + if let Some(keywords) = keywords_number { + if keywords & AUDIT_SUCCESS_MASK != 0 { + Some(EventType::AuditSuccess) + } else if keywords & AUDIT_FAILURE_MASK != 0 { + Some(EventType::AuditFailure) + } else { + None + } + } else { + None + } + } + Some(_) => match level_opt { + Some(1) => Some(EventType::Critical), + Some(2) => Some(EventType::Error), + Some(3) => Some(EventType::Warning), + Some(4) => Some(EventType::Info), + Some(5) => Some(EventType::Verbose), + _ => None, + }, + None => None, + } +} + +#[derive(Display)] +#[repr(u8)] +enum Severity { + #[strum(to_string = "DEBUG")] + Debug = 1, + #[strum(to_string = "INFO")] + Info = 2, + #[strum(to_string = "WARNING")] + Warning = 3, + #[strum(to_string = "ERROR")] + Error = 4, + #[strum(to_string = "CRITICAL")] + Critical = 5, +} + +impl From for Severity { + fn from(event_type: EventType) -> Severity { + match event_type { + EventType::AuditSuccess => Severity::Info, + EventType::AuditFailure => Severity::Error, + EventType::Critical => Severity::Critical, + EventType::Error => Severity::Error, + EventType::Warning => Severity::Warning, + EventType::Info => Severity::Info, + EventType::Verbose => Severity::Debug, + } + } +} + +#[derive(Debug, Default, Serialize, Clone)] +struct RenderingInfo { + #[serde(rename = "Message", skip_serializing_if = "Option::is_none")] + message: Option, + #[serde(rename = "Category", skip_serializing_if = "Option::is_none")] + task: Option, + #[serde(rename = "Opcode", skip_serializing_if = "Option::is_none")] + opcode: Option, +} + +impl From for RenderingInfo { + fn from(value: crate::event::RenderingInfo) -> Self { + Self { + message: value.message, + task: value.task, + opcode: value.opcode, + } + } +} + +#[cfg(test)] +mod tests { + use std::{net::SocketAddr, str::FromStr, sync::Arc}; + + use chrono::Utc; + use common::subscription::SubscriptionData; + use common::subscription::SubscriptionUuid; + use serde_json::Value; + use uuid::Uuid; + + use crate::{ + event::{EventData, EventMetadata}, + formats::nxlog::NxlogFormat, + output::OutputFormat, + subscription::Subscription, + }; + + fn compare(xml: &str, expected_json: &str) { + // Generate metadata + let mut subscription_data = SubscriptionData::new("Test", ""); + subscription_data + .set_uuid(SubscriptionUuid( + Uuid::from_str("8B18D83D-2964-4F35-AC3B-6F4E6FFA727B").unwrap(), + )) + .set_uri(Some("/this/is/a/test".to_string())) + .set_revision(Some("BABAR".to_string())); + let subscription = Subscription::try_from(subscription_data).unwrap(); + + let mut metadata = EventMetadata::new( + &SocketAddr::from_str("192.168.58.100:5985").unwrap(), + "WIN10$@WINDOMAIN.LOCAL", + Some("openwec".to_owned()), + &subscription, + "188BB736-9441-5C66-188B-B73694415C66".to_string(), + Some("TOTO".to_string()), + ); + metadata.set_time_received( + chrono::DateTime::parse_from_rfc3339("2024-03-14T14:54:20.331+01:00") + .unwrap() + .with_timezone(&Utc), + ); + + // Format event and compare with expected result + let event_data = EventData::new(Arc::new(xml.to_string()), true); + assert!(event_data.event().unwrap().additional.error.is_none()); + + let formatter = NxlogFormat; + let result = formatter.format(&metadata, &event_data).unwrap(); + + let event_json_value: Value = serde_json::from_str(&result).unwrap(); + let expected_value: Value = serde_json::from_str(expected_json).unwrap(); + + assert_eq!(event_json_value, expected_value); + } + + const EVENT_4624: &str = r#"4624301254400x80200000000000001446SecurityWKS10001S-1-5-18WKS10001$WORKGROUP0x3e7S-1-5-21-1430380458-3079459327-630937868-1001userWKS100010x615a442User32 NegotiateWKS10001{00000000-0000-0000-0000-000000000000}--00x5c8C:\Windows\System32\svchost.exe127.0.0.10%%1833----%%18430x615a61%%1842An account was successfully logged on. Subject: Security ID: S-1-5-18 Account Name: WKS10001$ Account Domain: WORKGROUP Logon ID: 0x3E7 Logon Information: Logon Type: 2 Restricted Admin Mode: - Remote Credential Guard: - Virtual Account: No Elevated Token: Yes Impersonation Level: Impersonation New Logon: Security ID: S-1-5-21-1430380458-3079459327-630937868-1001 Account Name: user Account Domain: WKS10001 Logon ID: 0x615A44 Linked Logon ID: 0x615A61 Network Account Name: - Network Account Domain: - Logon GUID: {00000000-0000-0000-0000-000000000000} Process Information: Process ID: 0x5c8 Process Name: C:\Windows\System32\svchost.exe Network Information: Workstation Name: WKS10001 Source Network Address: 127.0.0.1 Source Port: 0 Detailed Authentication Information: Logon Process: User32 Authentication Package: Negotiate Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that was logged on. The network fields indicate where a remote logon request originated. Workstation name is not always available and may be left blank in some cases. The impersonation level field indicates the extent to which a process in the logon session can impersonate. The authentication information fields provide detailed information about this specific logon request. - Logon GUID is a unique identifier that can be used to correlate this event with a KDC event. - Transited services indicate which intermediate services have participated in this logon request. - Package name indicates which sub-protocol was used among the NTLM protocols. - Key length indicates the length of the generated session key. This will be 0 if no session key was requested.InformationLogonInfoSecurityMicrosoft Windows security auditing.Audit Success "#; + const EVENT_4624_JSON: &str = r#"{"EventTime":"2024-03-14T13:54:19.3628662Z","Hostname":"WKS10001","Keywords":-9214364837600034816,"EventType":"AUDIT_SUCCESS","SeverityValue":2,"Severity":"INFO","EventID":4624,"SourceName":"Microsoft-Windows-Security-Auditing","ProviderGuid":"{54849625-5478-4994-A5BA-3E3B0328C30D}","Version":3,"Task":12544,"OpcodeValue":0,"RecordNumber":1446,"ActivityID":"{B073A4BF-7611-0000-BCA5-73B01176DA01}","ProcessID":780,"ThreadID":2832,"Channel":"Security","Message":"An account was successfully logged on.\r\n\r\nSubject:\r\n\tSecurity ID:\t\tS-1-5-18\r\n\tAccount Name:\t\tWKS10001$\r\n\tAccount Domain:\t\tWORKGROUP\r\n\tLogon ID:\t\t0x3E7\r\n\r\nLogon Information:\r\n\tLogon Type:\t\t2\r\n\tRestricted Admin Mode:\t-\r\n\tRemote Credential Guard:\t-\r\n\tVirtual Account:\t\tNo\r\n\tElevated Token:\t\tYes\r\n\r\nImpersonation Level:\t\tImpersonation\r\n\r\nNew Logon:\r\n\tSecurity ID:\t\tS-1-5-21-1430380458-3079459327-630937868-1001\r\n\tAccount Name:\t\tuser\r\n\tAccount Domain:\t\tWKS10001\r\n\tLogon ID:\t\t0x615A44\r\n\tLinked Logon ID:\t\t0x615A61\r\n\tNetwork Account Name:\t-\r\n\tNetwork Account Domain:\t-\r\n\tLogon GUID:\t\t{00000000-0000-0000-0000-000000000000}\r\n\r\nProcess Information:\r\n\tProcess ID:\t\t0x5c8\r\n\tProcess Name:\t\tC:\\Windows\\System32\\svchost.exe\r\n\r\nNetwork Information:\r\n\tWorkstation Name:\tWKS10001\r\n\tSource Network Address:\t127.0.0.1\r\n\tSource Port:\t\t0\r\n\r\nDetailed Authentication Information:\r\n\tLogon Process:\t\tUser32 \r\n\tAuthentication Package:\tNegotiate\r\n\tTransited Services:\t-\r\n\tPackage Name (NTLM only):\t-\r\n\tKey Length:\t\t0\r\n\r\nThis event is generated when a logon session is created. It is generated on the computer that was accessed.\r\n\r\nThe subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe.\r\n\r\nThe logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network).\r\n\r\nThe New Logon fields indicate the account for whom the new logon was created, i.e. the account that was logged on.\r\n\r\nThe network fields indicate where a remote logon request originated. Workstation name is not always available and may be left blank in some cases.\r\n\r\nThe impersonation level field indicates the extent to which a process in the logon session can impersonate.\r\n\r\nThe authentication information fields provide detailed information about this specific logon request.\r\n\t- Logon GUID is a unique identifier that can be used to correlate this event with a KDC event.\r\n\t- Transited services indicate which intermediate services have participated in this logon request.\r\n\t- Package name indicates which sub-protocol was used among the NTLM protocols.\r\n\t- Key length indicates the length of the generated session key. This will be 0 if no session key was requested.","Category":"Logon","Opcode":"Info","SubjectUserSid":"S-1-5-18","SubjectUserName":"WKS10001$","SubjectDomainName":"WORKGROUP","SubjectLogonId":"0x3e7","TargetUserSid":"S-1-5-21-1430380458-3079459327-630937868-1001","TargetUserName":"user","TargetDomainName":"WKS10001","TargetLogonId":"0x615a44","LogonType":"2","LogonProcessName":"User32 ","AuthenticationPackageName":"Negotiate","WorkstationName":"WKS10001","LogonGuid":"{00000000-0000-0000-0000-000000000000}","TransmittedServices":"-","LmPackageName":"-","KeyLength":"0","ProcessName":"C:\\Windows\\System32\\svchost.exe","IpAddress":"127.0.0.1","IpPort":"0","ImpersonationLevel":"%%1833","RestrictedAdminMode":"-","RemoteCredentialGuard":"-","TargetOutboundUserName":"-","TargetOutboundDomainName":"-","VirtualAccount":"%%1843","TargetLinkedLogonId":"0x615a61","ElevatedToken":"%%1842","EventReceivedTime":"2024-03-14T13:54:20.331+00:00","OpenWEC":{"IpAddress":"192.168.58.100","TimeReceived":"2024-03-14T13:54:20.331+00:00","Principal":"WIN10$@WINDOMAIN.LOCAL","Subscription":{"Uuid":"8B18D83D-2964-4F35-AC3B-6F4E6FFA727B","Version":"188BB736-9441-5C66-188B-B73694415C66","Name":"Test","Uri":"/this/is/a/test","ServerRevision":"BABAR","ClientRevision":"TOTO"},"Node":"openwec"}, "ProcessId": "0x5c8"}"#; + + #[test] + fn test_serialize_4624_event_data() { + compare(EVENT_4624, EVENT_4624_JSON) + } + + const EVENT_1003: &str = r#"100304000x80000000000000403ApplicationWKS1000155c92734-d682-4d71-983e-d6ec3f16059f +1: 040fa323-92b1-4baf-97a2-5b67feaefddb, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +2: 0724cb7d-3437-4cb7-93cb-830375d0079d, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +3: 0ad2ac98-7bb9-4201-8d92-312299201369, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +4: 1a9a717a-cf13-4ba5-83c3-0fe25fa868d5, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +5: 221a02da-e2a1-4b75-864c-0a4410a33fdf, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +6: 291ece0e-9c38-40ca-a9e1-32cc7ec19507, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +7: 2936d1d2-913a-4542-b54e-ce5a602a2a38, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +8: 2c293c26-a45a-4a2a-a350-c69a67097529, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +9: 2de67392-b7a7-462a-b1ca-108dd189f588, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +10: 2ffd8952-423e-4903-b993-72a1aa44cf82, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +11: 30a42c86-b7a0-4a34-8c90-ff177cb2acb7, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +12: 345a5db0-d94f-4e3b-a0c0-7c42f7bc3ebf, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +13: 3502365a-f88a-4ba4-822a-5769d3073b65, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +14: 377333b1-8b5d-48d6-9679-1225c872d37c, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +15: 3df374ef-d444-4494-a5a1-4b0d9fd0e203, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +16: 3f1afc82-f8ac-4f6c-8005-1d233e606eee, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +17: 49cd895b-53b2-4dc4-a5f7-b18aa019ad37, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +18: 4de7cb65-cdf1-4de9-8ae8-e3cce27b9f2c, 1, 1 [(0 )(1 )(2 [0xC004E003, 0, 0], [( 1 0xC004F034)( 1 0xC004F034)(?)(?)(?)(?)(?)(?)])(3 [0x00000000, 0, 0], [( 6 0xC004F009 0 0)( 1 0x00000000)( 6 0xC004F009 0 0)(?)(?)(?)( 10 0x00000000 msft:rm/algorithm/flags/1.0)( 11 0x00000000 0xC004F034)])] +19: 4f3da0d2-271d-4508-ae81-626b60809a38, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +20: 5d78c4e9-aeb3-4b40-8ac2-6a6005e0ad6d, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +21: 60b3ec1b-9545-4921-821f-311b129dd6f6, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +22: 613d217f-7f13-4268-9907-1662339531cd, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +23: 62f0c100-9c53-4e02-b886-a3528ddfe7f6, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +24: 6365275e-368d-46ca-a0ef-fc0404119333, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +25: 721f9237-9341-4453-a661-09e8baa6cca5, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +26: 73111121-5638-40f6-bc11-f1d7b0d64300, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +27: 7a802526-4c94-4bd1-ba14-835a1aca2120, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +28: 7cb546c0-c7d5-44d8-9a5c-69ecdd782b69, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +29: 82bbc092-bc50-4e16-8e18-b74fc486aec3, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +30: 8ab9bdd1-1f67-4997-82d9-8878520837d9, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +31: 8b351c9c-f398-4515-9900-09df49427262, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +32: 90da7373-1c51-430b-bf26-c97e9c5cdc31, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +33: 92fb8726-92a8-4ffc-94ce-f82e07444653, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +34: 95dca82f-385d-4d39-b85b-5c73fa285d6f, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +35: a48938aa-62fa-4966-9d44-9f04da3f72f2, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +36: b0773a15-df3a-4312-9ad2-83d69648e356, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +37: b4bfe195-541e-4e64-ad23-6177f19e395e, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +38: b68e61d2-68ca-4757-be45-0cc2f3e68eee, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +39: bd3762d7-270d-4760-8fb3-d829ca45278a, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +40: c86d5194-4840-4dae-9c1c-0301003a5ab0, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +41: ca7df2e3-5ea0-47b8-9ac1-b1be4d8edd69, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +42: d552befb-48cc-4327-8f39-47d2d94f987c, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +43: d6eadb3b-5ca8-4a6b-986e-35b550756111, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +44: df96023b-dcd9-4be2-afa0-c6c871159ebe, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +45: e0c42288-980c-4788-a014-c080d2e1926e, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +46: e4db50ea-bda1-4566-b047-0ca50abc6f07, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +47: e558417a-5123-4f6f-91e7-385c1c7ca9d4, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +48: e7a950a2-e548-4f10-bf16-02ec848e0643, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +49: eb6d346f-1c60-4643-b960-40ec31596c45, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +50: ec868e65-fadf-4759-b23e-93fe37f2cc29, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +51: ef51e000-2659-4f25-8345-3de70a9cf4c4, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +52: f7af7d09-40e4-419c-a49b-eae366689ebd, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +53: fa755fe6-6739-40b9-8d84-6d0ea3b6d1ab, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] +54: fe74f55b-0338-41d6-b267-4a201abe7285, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] + +The Software Protection service has completed licensing status check. Application Id=55c92734-d682-4d71-983e-d6ec3f16059f Licensing Status= 1: 040fa323-92b1-4baf-97a2-5b67feaefddb, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 2: 0724cb7d-3437-4cb7-93cb-830375d0079d, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 3: 0ad2ac98-7bb9-4201-8d92-312299201369, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 4: 1a9a717a-cf13-4ba5-83c3-0fe25fa868d5, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 5: 221a02da-e2a1-4b75-864c-0a4410a33fdf, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 6: 291ece0e-9c38-40ca-a9e1-32cc7ec19507, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 7: 2936d1d2-913a-4542-b54e-ce5a602a2a38, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 8: 2c293c26-a45a-4a2a-a350-c69a67097529, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 9: 2de67392-b7a7-462a-b1ca-108dd189f588, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 10: 2ffd8952-423e-4903-b993-72a1aa44cf82, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 11: 30a42c86-b7a0-4a34-8c90-ff177cb2acb7, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 12: 345a5db0-d94f-4e3b-a0c0-7c42f7bc3ebf, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 13: 3502365a-f88a-4ba4-822a-5769d3073b65, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 14: 377333b1-8b5d-48d6-9679-1225c872d37c, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 15: 3df374ef-d444-4494-a5a1-4b0d9fd0e203, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 16: 3f1afc82-f8ac-4f6c-8005-1d233e606eee, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 17: 49cd895b-53b2-4dc4-a5f7-b18aa019ad37, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 18: 4de7cb65-cdf1-4de9-8ae8-e3cce27b9f2c, 1, 1 [(0 )(1 )(2 [0xC004E003, 0, 0], [( 1 0xC004F034)( 1 0xC004F034)(?)(?)(?)(?)(?)(?)])(3 [0x00000000, 0, 0], [( 6 0xC004F009 0 0)( 1 0x00000000)( 6 0xC004F009 0 0)(?)(?)(?)( 10 0x00000000 msft:rm/algorithm/flags/1.0)( 11 0x00000000 0xC004F034)])] 19: 4f3da0d2-271d-4508-ae81-626b60809a38, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 20: 5d78c4e9-aeb3-4b40-8ac2-6a6005e0ad6d, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 21: 60b3ec1b-9545-4921-821f-311b129dd6f6, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 22: 613d217f-7f13-4268-9907-1662339531cd, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 23: 62f0c100-9c53-4e02-b886-a3528ddfe7f6, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 24: 6365275e-368d-46ca-a0ef-fc0404119333, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 25: 721f9237-9341-4453-a661-09e8baa6cca5, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 26: 73111121-5638-40f6-bc11-f1d7b0d64300, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 27: 7a802526-4c94-4bd1-ba14-835a1aca2120, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 28: 7cb546c0-c7d5-44d8-9a5c-69ecdd782b69, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 29: 82bbc092-bc50-4e16-8e18-b74fc486aec3, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 30: 8ab9bdd1-1f67-4997-82d9-8878520837d9, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 31: 8b351c9c-f398-4515-9900-09df49427262, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 32: 90da7373-1c51-430b-bf26-c97e9c5cdc31, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 33: 92fb8726-92a8-4ffc-94ce-f82e07444653, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 34: 95dca82f-385d-4d39-b85b-5c73fa285d6f, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 35: a48938aa-62fa-4966-9d44-9f04da3f72f2, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 36: b0773a15-df3a-4312-9ad2-83d69648e356, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 37: b4bfe195-541e-4e64-ad23-6177f19e395e, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 38: b68e61d2-68ca-4757-be45-0cc2f3e68eee, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 39: bd3762d7-270d-4760-8fb3-d829ca45278a, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 40: c86d5194-4840-4dae-9c1c-0301003a5ab0, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 41: ca7df2e3-5ea0-47b8-9ac1-b1be4d8edd69, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 42: d552befb-48cc-4327-8f39-47d2d94f987c, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 43: d6eadb3b-5ca8-4a6b-986e-35b550756111, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 44: df96023b-dcd9-4be2-afa0-c6c871159ebe, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 45: e0c42288-980c-4788-a014-c080d2e1926e, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 46: e4db50ea-bda1-4566-b047-0ca50abc6f07, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 47: e558417a-5123-4f6f-91e7-385c1c7ca9d4, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 48: e7a950a2-e548-4f10-bf16-02ec848e0643, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 49: eb6d346f-1c60-4643-b960-40ec31596c45, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 50: ec868e65-fadf-4759-b23e-93fe37f2cc29, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 51: ef51e000-2659-4f25-8345-3de70a9cf4c4, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 52: f7af7d09-40e4-419c-a49b-eae366689ebd, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 53: fa755fe6-6739-40b9-8d84-6d0ea3b6d1ab, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] 54: fe74f55b-0338-41d6-b267-4a201abe7285, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )] InformationMicrosoft-Windows-Security-SPPClassic"#; + const EVENT_1003_JSON: &str = r#"{"EventTime":"2024-03-14T13:54:25.0379869Z","Hostname":"WKS10001","Keywords":36028797018963968,"EventType":"INFO","SeverityValue":2,"Severity":"INFO","EventID":1003,"SourceName":"Microsoft-Windows-Security-SPP","ProviderGuid":"{E23B33B0-C8C9-472C-A5F9-F2BDFEA0F156}","Version":0,"Task":0,"OpcodeValue":0,"RecordNumber":403,"ProcessID":6628,"ThreadID":0,"Channel":"Application","Message":"The Software Protection service has completed licensing status check.\r\nApplication Id=55c92734-d682-4d71-983e-d6ec3f16059f\r\nLicensing Status=\n1: 040fa323-92b1-4baf-97a2-5b67feaefddb, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n2: 0724cb7d-3437-4cb7-93cb-830375d0079d, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n3: 0ad2ac98-7bb9-4201-8d92-312299201369, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n4: 1a9a717a-cf13-4ba5-83c3-0fe25fa868d5, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n5: 221a02da-e2a1-4b75-864c-0a4410a33fdf, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n6: 291ece0e-9c38-40ca-a9e1-32cc7ec19507, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n7: 2936d1d2-913a-4542-b54e-ce5a602a2a38, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n8: 2c293c26-a45a-4a2a-a350-c69a67097529, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n9: 2de67392-b7a7-462a-b1ca-108dd189f588, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n10: 2ffd8952-423e-4903-b993-72a1aa44cf82, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n11: 30a42c86-b7a0-4a34-8c90-ff177cb2acb7, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n12: 345a5db0-d94f-4e3b-a0c0-7c42f7bc3ebf, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n13: 3502365a-f88a-4ba4-822a-5769d3073b65, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n14: 377333b1-8b5d-48d6-9679-1225c872d37c, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n15: 3df374ef-d444-4494-a5a1-4b0d9fd0e203, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n16: 3f1afc82-f8ac-4f6c-8005-1d233e606eee, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n17: 49cd895b-53b2-4dc4-a5f7-b18aa019ad37, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n18: 4de7cb65-cdf1-4de9-8ae8-e3cce27b9f2c, 1, 1 [(0 )(1 )(2 [0xC004E003, 0, 0], [( 1 0xC004F034)( 1 0xC004F034)(?)(?)(?)(?)(?)(?)])(3 [0x00000000, 0, 0], [( 6 0xC004F009 0 0)( 1 0x00000000)( 6 0xC004F009 0 0)(?)(?)(?)( 10 0x00000000 msft:rm/algorithm/flags/1.0)( 11 0x00000000 0xC004F034)])]\n19: 4f3da0d2-271d-4508-ae81-626b60809a38, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n20: 5d78c4e9-aeb3-4b40-8ac2-6a6005e0ad6d, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n21: 60b3ec1b-9545-4921-821f-311b129dd6f6, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n22: 613d217f-7f13-4268-9907-1662339531cd, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n23: 62f0c100-9c53-4e02-b886-a3528ddfe7f6, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n24: 6365275e-368d-46ca-a0ef-fc0404119333, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n25: 721f9237-9341-4453-a661-09e8baa6cca5, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n26: 73111121-5638-40f6-bc11-f1d7b0d64300, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n27: 7a802526-4c94-4bd1-ba14-835a1aca2120, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n28: 7cb546c0-c7d5-44d8-9a5c-69ecdd782b69, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n29: 82bbc092-bc50-4e16-8e18-b74fc486aec3, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n30: 8ab9bdd1-1f67-4997-82d9-8878520837d9, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n31: 8b351c9c-f398-4515-9900-09df49427262, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n32: 90da7373-1c51-430b-bf26-c97e9c5cdc31, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n33: 92fb8726-92a8-4ffc-94ce-f82e07444653, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n34: 95dca82f-385d-4d39-b85b-5c73fa285d6f, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n35: a48938aa-62fa-4966-9d44-9f04da3f72f2, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n36: b0773a15-df3a-4312-9ad2-83d69648e356, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n37: b4bfe195-541e-4e64-ad23-6177f19e395e, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n38: b68e61d2-68ca-4757-be45-0cc2f3e68eee, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n39: bd3762d7-270d-4760-8fb3-d829ca45278a, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n40: c86d5194-4840-4dae-9c1c-0301003a5ab0, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n41: ca7df2e3-5ea0-47b8-9ac1-b1be4d8edd69, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n42: d552befb-48cc-4327-8f39-47d2d94f987c, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n43: d6eadb3b-5ca8-4a6b-986e-35b550756111, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n44: df96023b-dcd9-4be2-afa0-c6c871159ebe, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n45: e0c42288-980c-4788-a014-c080d2e1926e, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n46: e4db50ea-bda1-4566-b047-0ca50abc6f07, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n47: e558417a-5123-4f6f-91e7-385c1c7ca9d4, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n48: e7a950a2-e548-4f10-bf16-02ec848e0643, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n49: eb6d346f-1c60-4643-b960-40ec31596c45, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n50: ec868e65-fadf-4759-b23e-93fe37f2cc29, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n51: ef51e000-2659-4f25-8345-3de70a9cf4c4, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n52: f7af7d09-40e4-419c-a49b-eae366689ebd, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n53: fa755fe6-6739-40b9-8d84-6d0ea3b6d1ab, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n54: fe74f55b-0338-41d6-b267-4a201abe7285, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n\n","EventReceivedTime":"2024-03-14T13:54:20.331+00:00","Data":["55c92734-d682-4d71-983e-d6ec3f16059f","\n1: 040fa323-92b1-4baf-97a2-5b67feaefddb, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n2: 0724cb7d-3437-4cb7-93cb-830375d0079d, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n3: 0ad2ac98-7bb9-4201-8d92-312299201369, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n4: 1a9a717a-cf13-4ba5-83c3-0fe25fa868d5, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n5: 221a02da-e2a1-4b75-864c-0a4410a33fdf, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n6: 291ece0e-9c38-40ca-a9e1-32cc7ec19507, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n7: 2936d1d2-913a-4542-b54e-ce5a602a2a38, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n8: 2c293c26-a45a-4a2a-a350-c69a67097529, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n9: 2de67392-b7a7-462a-b1ca-108dd189f588, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n10: 2ffd8952-423e-4903-b993-72a1aa44cf82, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n11: 30a42c86-b7a0-4a34-8c90-ff177cb2acb7, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n12: 345a5db0-d94f-4e3b-a0c0-7c42f7bc3ebf, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n13: 3502365a-f88a-4ba4-822a-5769d3073b65, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n14: 377333b1-8b5d-48d6-9679-1225c872d37c, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n15: 3df374ef-d444-4494-a5a1-4b0d9fd0e203, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n16: 3f1afc82-f8ac-4f6c-8005-1d233e606eee, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n17: 49cd895b-53b2-4dc4-a5f7-b18aa019ad37, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n18: 4de7cb65-cdf1-4de9-8ae8-e3cce27b9f2c, 1, 1 [(0 )(1 )(2 [0xC004E003, 0, 0], [( 1 0xC004F034)( 1 0xC004F034)(?)(?)(?)(?)(?)(?)])(3 [0x00000000, 0, 0], [( 6 0xC004F009 0 0)( 1 0x00000000)( 6 0xC004F009 0 0)(?)(?)(?)( 10 0x00000000 msft:rm/algorithm/flags/1.0)( 11 0x00000000 0xC004F034)])]\n19: 4f3da0d2-271d-4508-ae81-626b60809a38, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n20: 5d78c4e9-aeb3-4b40-8ac2-6a6005e0ad6d, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n21: 60b3ec1b-9545-4921-821f-311b129dd6f6, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n22: 613d217f-7f13-4268-9907-1662339531cd, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n23: 62f0c100-9c53-4e02-b886-a3528ddfe7f6, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n24: 6365275e-368d-46ca-a0ef-fc0404119333, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n25: 721f9237-9341-4453-a661-09e8baa6cca5, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n26: 73111121-5638-40f6-bc11-f1d7b0d64300, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n27: 7a802526-4c94-4bd1-ba14-835a1aca2120, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n28: 7cb546c0-c7d5-44d8-9a5c-69ecdd782b69, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n29: 82bbc092-bc50-4e16-8e18-b74fc486aec3, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n30: 8ab9bdd1-1f67-4997-82d9-8878520837d9, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n31: 8b351c9c-f398-4515-9900-09df49427262, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n32: 90da7373-1c51-430b-bf26-c97e9c5cdc31, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n33: 92fb8726-92a8-4ffc-94ce-f82e07444653, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n34: 95dca82f-385d-4d39-b85b-5c73fa285d6f, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n35: a48938aa-62fa-4966-9d44-9f04da3f72f2, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n36: b0773a15-df3a-4312-9ad2-83d69648e356, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n37: b4bfe195-541e-4e64-ad23-6177f19e395e, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n38: b68e61d2-68ca-4757-be45-0cc2f3e68eee, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n39: bd3762d7-270d-4760-8fb3-d829ca45278a, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n40: c86d5194-4840-4dae-9c1c-0301003a5ab0, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n41: ca7df2e3-5ea0-47b8-9ac1-b1be4d8edd69, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n42: d552befb-48cc-4327-8f39-47d2d94f987c, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n43: d6eadb3b-5ca8-4a6b-986e-35b550756111, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n44: df96023b-dcd9-4be2-afa0-c6c871159ebe, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n45: e0c42288-980c-4788-a014-c080d2e1926e, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n46: e4db50ea-bda1-4566-b047-0ca50abc6f07, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n47: e558417a-5123-4f6f-91e7-385c1c7ca9d4, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n48: e7a950a2-e548-4f10-bf16-02ec848e0643, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n49: eb6d346f-1c60-4643-b960-40ec31596c45, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n50: ec868e65-fadf-4759-b23e-93fe37f2cc29, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n51: ef51e000-2659-4f25-8345-3de70a9cf4c4, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n52: f7af7d09-40e4-419c-a49b-eae366689ebd, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n53: fa755fe6-6739-40b9-8d84-6d0ea3b6d1ab, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n54: fe74f55b-0338-41d6-b267-4a201abe7285, 1, 0 [(0 [0xC004F014, 0, 0], [(?)(?)(?)(?)(?)(?)(?)(?)])(1 )(2 )(3 )]\n\n"],"OpenWEC":{"IpAddress":"192.168.58.100","TimeReceived":"2024-03-14T13:54:20.331+00:00","Principal":"WIN10$@WINDOMAIN.LOCAL","Subscription":{"Uuid":"8B18D83D-2964-4F35-AC3B-6F4E6FFA727B","Version":"188BB736-9441-5C66-188B-B73694415C66","Name":"Test","Uri":"/this/is/a/test","ServerRevision":"BABAR","ClientRevision":"TOTO"},"Node":"openwec"}}"#; + + #[test] + fn test_serialize_1003_event_data_unamed() { + compare(EVENT_1003, EVENT_1003_JSON); + } + + const EVENT_8198: &str = r#"819802000x80000000000000405ApplicationWKS10001hr=0x800704CFRuleId=31e71c49-8da7-4a2f-ad92-45d98a1c79ba;Action=AutoActivate;AppId=55c92734-d682-4d71-983e-d6ec3f16059f;SkuId=4de7cb65-cdf1-4de9-8ae8-e3cce27b9f2c;NotificationInterval=1440;Trigger=UserLogon;SessionId=2License Activation (slui.exe) failed with the following error code: hr=0x800704CF Command-line arguments: RuleId=31e71c49-8da7-4a2f-ad92-45d98a1c79ba;Action=AutoActivate;AppId=55c92734-d682-4d71-983e-d6ec3f16059f;SkuId=4de7cb65-cdf1-4de9-8ae8-e3cce27b9f2c;NotificationInterval=1440;Trigger=UserLogon;SessionId=2ErrorMicrosoft-Windows-Security-SPPClassic"#; + const EVENT_8198_JSON: &str = r#"{"Data":["hr=0x800704CF","RuleId=31e71c49-8da7-4a2f-ad92-45d98a1c79ba;Action=AutoActivate;AppId=55c92734-d682-4d71-983e-d6ec3f16059f;SkuId=4de7cb65-cdf1-4de9-8ae8-e3cce27b9f2c;NotificationInterval=1440;Trigger=UserLogon;SessionId=2"],"EventTime":"2024-03-14T13:54:25.1166916Z","Hostname":"WKS10001","Keywords":36028797018963968,"EventType":"ERROR","SeverityValue":4,"Severity":"ERROR","EventID":8198,"SourceName":"Microsoft-Windows-Security-SPP","ProviderGuid":"{E23B33B0-C8C9-472C-A5F9-F2BDFEA0F156}","Version":0,"Task":0,"OpcodeValue":0,"RecordNumber":405,"ProcessID":7240,"ThreadID":0,"Channel":"Application","Message":"License Activation (slui.exe) failed with the following error code:\r\nhr=0x800704CF\r\nCommand-line arguments:\r\nRuleId=31e71c49-8da7-4a2f-ad92-45d98a1c79ba;Action=AutoActivate;AppId=55c92734-d682-4d71-983e-d6ec3f16059f;SkuId=4de7cb65-cdf1-4de9-8ae8-e3cce27b9f2c;NotificationInterval=1440;Trigger=UserLogon;SessionId=2","EventReceivedTime":"2024-03-14T13:54:20.331+00:00","OpenWEC":{"IpAddress":"192.168.58.100","Node":"openwec","Principal":"WIN10$@WINDOMAIN.LOCAL","Subscription":{"Name": "Test","Uri":"/this/is/a/test","Uuid":"8B18D83D-2964-4F35-AC3B-6F4E6FFA727B","Version":"188BB736-9441-5C66-188B-B73694415C66","ServerRevision":"BABAR","ClientRevision":"TOTO"},"TimeReceived":"2024-03-14T13:54:20.331+00:00"}}"#; + + #[test] + fn test_serialize_8198() { + compare(EVENT_8198, EVENT_8198_JSON) + } + + const EVENT_8002: &str = r#"8002038001130x80001000000000004974Microsoft-Windows-Store/OperationalWKS10001Trying to remove timer {5691E7B0-78A4-A20B-3094-CD9BCC47193D} not in tableMemoryTimerService::CancelTimerWithIdonecoreuap\enduser\winstore\licensemanager\lib\memorytimer.cpp80Trying to remove timer {5691E7B0-78A4-A20B-3094-CD9BCC47193D} not in table Function: MemoryTimerService::CancelTimerWithId Source: onecoreuap\enduser\winstore\licensemanager\lib\memorytimer.cpp (80)WarningLMWarningMicrosoft-Windows-Store"#; + const EVENT_8002_JSON: &str = r#"{"EventTime":"2024-03-14T13:54:11.8558403Z","Hostname":"WKS10001","Keywords":-9223354444668731392,"EventType":"WARNING","SeverityValue":3,"Severity":"WARNING","EventID":8002,"SourceName":"Microsoft-Windows-Store","ProviderGuid":"{9C2A37F3-E5FD-5CAE-BCD1-43DAFEEE1FF0}","Version":0,"Task":8001,"OpcodeValue":13,"RecordNumber":4974,"ProcessID":5496,"ThreadID":3248,"Channel":"Microsoft-Windows-Store/Operational","UserID":"S-1-5-19","Message":"Trying to remove timer {5691E7B0-78A4-A20B-3094-CD9BCC47193D} not in table\r\nFunction: MemoryTimerService::CancelTimerWithId\r\nSource: onecoreuap\\enduser\\winstore\\licensemanager\\lib\\memorytimer.cpp (80)","Category":"LM","Opcode":"Warning","Function":"MemoryTimerService::CancelTimerWithId","Source":"onecoreuap\\enduser\\winstore\\licensemanager\\lib\\memorytimer.cpp","Line Number":"80","EventReceivedTime":"2024-03-14T13:54:20.331+00:00","OpenWEC":{"IpAddress":"192.168.58.100","Node":"openwec","Principal":"WIN10$@WINDOMAIN.LOCAL","Subscription":{"Name":"Test","Uri":"/this/is/a/test","Uuid":"8B18D83D-2964-4F35-AC3B-6F4E6FFA727B","Version":"188BB736-9441-5C66-188B-B73694415C66","ServerRevision":"BABAR","ClientRevision":"TOTO"},"TimeReceived":"2024-03-14T13:54:20.331+00:00"}}"#; + + #[test] + fn test_serialize_8002() { + compare(EVENT_8002, EVENT_8002_JSON) + } + + const EVENT_4625: &str = r#"4625001254400x80100000000000001444SecurityWKS10001S-1-5-18WKS10001$WORKGROUP0x3e7S-1-0-0userWKS100010xc000006d%%23130xc000006a2User32 NegotiateWKS10001--00x5c8C:\Windows\System32\svchost.exe127.0.0.10An account failed to log on. Subject: Security ID: S-1-5-18 Account Name: WKS10001$ Account Domain: WORKGROUP Logon ID: 0x3E7 Logon Type: 2 Account For Which Logon Failed: Security ID: S-1-0-0 Account Name: user Account Domain: WKS10001 Failure Information: Failure Reason: Unknown user name or bad password. Status: 0xC000006D Sub Status: 0xC000006A Process Information: Caller Process ID: 0x5c8 Caller Process Name: C:\Windows\System32\svchost.exe Network Information: Workstation Name: WKS10001 Source Network Address: 127.0.0.1 Source Port: 0 Detailed Authentication Information: Logon Process: User32 Authentication Package: Negotiate Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon request fails. It is generated on the computer where access was attempted. The Subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The Logon Type field indicates the kind of logon that was requested. The most common types are 2 (interactive) and 3 (network). The Process Information fields indicate which account and process on the system requested the logon. The Network Information fields indicate where a remote logon request originated. Workstation name is not always available and may be left blank in some cases. The authentication information fields provide detailed information about this specific logon request. - Transited services indicate which intermediate services have participated in this logon request. - Package name indicates which sub-protocol was used among the NTLM protocols. - Key length indicates the length of the generated session key. This will be 0 if no session key was requested.InformationLogonInfoSecurityMicrosoft Windows security auditing.Audit Failure"#; + const EVENT_4625_JSON: &str = r#"{"EventTime":"2024-03-14T13:54:16.6138329Z","Hostname":"WKS10001","Keywords":-9218868437227405312,"EventType":"AUDIT_FAILURE","SeverityValue":4,"Severity":"ERROR","EventID":4625,"SourceName":"Microsoft-Windows-Security-Auditing","ProviderGuid":"{54849625-5478-4994-A5BA-3E3B0328C30D}","Version":0,"Task":12544,"OpcodeValue":0,"RecordNumber":1444,"ActivityID":"{B073A4BF-7611-0000-BCA5-73B01176DA01}","ProcessID":780,"ThreadID":8372,"Channel":"Security","Message":"An account failed to log on.\r\n\r\nSubject:\r\n\tSecurity ID:\t\tS-1-5-18\r\n\tAccount Name:\t\tWKS10001$\r\n\tAccount Domain:\t\tWORKGROUP\r\n\tLogon ID:\t\t0x3E7\r\n\r\nLogon Type:\t\t\t2\r\n\r\nAccount For Which Logon Failed:\r\n\tSecurity ID:\t\tS-1-0-0\r\n\tAccount Name:\t\tuser\r\n\tAccount Domain:\t\tWKS10001\r\n\r\nFailure Information:\r\n\tFailure Reason:\t\tUnknown user name or bad password.\r\n\tStatus:\t\t\t0xC000006D\r\n\tSub Status:\t\t0xC000006A\r\n\r\nProcess Information:\r\n\tCaller Process ID:\t0x5c8\r\n\tCaller Process Name:\tC:\\Windows\\System32\\svchost.exe\r\n\r\nNetwork Information:\r\n\tWorkstation Name:\tWKS10001\r\n\tSource Network Address:\t127.0.0.1\r\n\tSource Port:\t\t0\r\n\r\nDetailed Authentication Information:\r\n\tLogon Process:\t\tUser32 \r\n\tAuthentication Package:\tNegotiate\r\n\tTransited Services:\t-\r\n\tPackage Name (NTLM only):\t-\r\n\tKey Length:\t\t0\r\n\r\nThis event is generated when a logon request fails. It is generated on the computer where access was attempted.\r\n\r\nThe Subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe.\r\n\r\nThe Logon Type field indicates the kind of logon that was requested. The most common types are 2 (interactive) and 3 (network).\r\n\r\nThe Process Information fields indicate which account and process on the system requested the logon.\r\n\r\nThe Network Information fields indicate where a remote logon request originated. Workstation name is not always available and may be left blank in some cases.\r\n\r\nThe authentication information fields provide detailed information about this specific logon request.\r\n\t- Transited services indicate which intermediate services have participated in this logon request.\r\n\t- Package name indicates which sub-protocol was used among the NTLM protocols.\r\n\t- Key length indicates the length of the generated session key. This will be 0 if no session key was requested.","Category":"Logon","Opcode":"Info","SubjectUserSid":"S-1-5-18","SubjectUserName":"WKS10001$","SubjectDomainName":"WORKGROUP","SubjectLogonId":"0x3e7","TargetUserSid":"S-1-0-0","TargetUserName":"user","TargetDomainName":"WKS10001","Status":"0xc000006d","FailureReason":"%%2313","SubStatus":"0xc000006a","LogonType":"2","LogonProcessName":"User32 ","AuthenticationPackageName":"Negotiate","WorkstationName":"WKS10001","TransmittedServices":"-","LmPackageName":"-","KeyLength":"0","ProcessName":"C:\\Windows\\System32\\svchost.exe","IpAddress":"127.0.0.1","IpPort":"0","EventReceivedTime":"2024-03-14T13:54:20.331+00:00","OpenWEC":{"IpAddress":"192.168.58.100","TimeReceived":"2024-03-14T13:54:20.331+00:00","Principal":"WIN10$@WINDOMAIN.LOCAL","Subscription":{"Uuid":"8B18D83D-2964-4F35-AC3B-6F4E6FFA727B","Version":"188BB736-9441-5C66-188B-B73694415C66","Name":"Test","Uri":"/this/is/a/test","ServerRevision":"BABAR","ClientRevision":"TOTO"},"Node":"openwec"},"ProcessId":"0x5c8"}"#; + + #[test] + fn test_serialize_4625() { + compare(EVENT_4625, EVENT_4625_JSON) + } + + const EVENT_328: &str = r#"32802000x400000000001000020Microsoft-Windows-AppXDeployment/OperationalWKS100010x800401f0Unable to determine packages to be installed during logon with error: 0x800401F0.ErrorInfoMicrosoft-Windows-AppXDeployment"#; + const EVENT_328_JSON: &str = r#"{"EventTime":"2024-03-14T13:54:19.4093952Z","Hostname":"WKS10001","Keywords":4611686018427453440,"EventType":"ERROR","SeverityValue":4,"Severity":"ERROR","EventID":328,"SourceName":"Microsoft-Windows-AppXDeployment","ProviderGuid":"{8127F6D4-59F9-4ABF-8952-3E3A02073D5F}","Version":0,"Task":0,"OpcodeValue":0,"RecordNumber":20,"ActivityID":"{61A55000-55E5-1017-0000-000000000000}","ProcessID":468,"ThreadID":4744,"Channel":"Microsoft-Windows-AppXDeployment/Operational","UserID":"S-1-5-18","Message":"Unable to determine packages to be installed during logon with error: 0x800401F0.","Opcode":"Info","ErrorCode":"0x800401f0","EventReceivedTime":"2024-03-14T13:54:20.331+00:00","OpenWEC":{"IpAddress":"192.168.58.100","TimeReceived":"2024-03-14T13:54:20.331+00:00","Principal":"WIN10$@WINDOMAIN.LOCAL","Subscription":{"Uuid":"8B18D83D-2964-4F35-AC3B-6F4E6FFA727B","Version":"188BB736-9441-5C66-188B-B73694415C66","Name":"Test","Uri":"/this/is/a/test","ServerRevision":"BABAR","ClientRevision":"TOTO"},"Node":"openwec"}}"#; + + #[test] + fn test_serialize_328() { + compare(EVENT_328, EVENT_328_JSON) + } + + const EVENT_1100: &str = r#"11000410300x4020000000000000114371Securitywin10.windomain.localThe event logging service has shut down.InformationService shutdownInfoSecurityMicrosoft-Windows-EventlogAudit Success"#; + const EVENT_1100_JSON: &str = r#"{"SourceName":"Microsoft-Windows-Eventlog","ProviderGuid":"{FC65DDD8-D6EF-4962-83D5-6E5CFE9CE148}","EventID":1100,"Version":0,"Task":103,"OpcodeValue":0,"Keywords":4620693217682128896,"EventTime":"2022-12-14T14:39:07.1686183Z","RecordNumber":114371,"ProcessID":496,"ThreadID":204,"Channel":"Security","Hostname":"win10.windomain.local","EventType":"AUDIT_SUCCESS","Severity":"INFO","SeverityValue":2,"UserData":"","Message":"The event logging service has shut down.","Category":"Service shutdown","Opcode":"Info","OpenWEC":{"IpAddress":"192.168.58.100","TimeReceived":"2024-03-14T13:54:20.331+00:00","Principal":"WIN10$@WINDOMAIN.LOCAL","Subscription":{"Uuid":"8B18D83D-2964-4F35-AC3B-6F4E6FFA727B","Version":"188BB736-9441-5C66-188B-B73694415C66","Name":"Test","Uri":"/this/is/a/test","ClientRevision":"TOTO","ServerRevision":"BABAR"},"Node":"openwec"},"EventReceivedTime":"2024-03-14T13:54:20.331+00:00"}"#; + + #[test] + fn test_serialize_1100() { + // UserData + compare(EVENT_1100, EVENT_1100_JSON) + } +} diff --git a/server/src/output.rs b/server/src/output.rs index 58058df..7c0247d 100644 --- a/server/src/output.rs +++ b/server/src/output.rs @@ -11,7 +11,7 @@ use crate::{ files::OutputFiles, kafka::OutputKafka, redis::OutputRedis, tcp::OutputTcp, unix::OutputUnixDatagram, }, - event::{EventData, EventMetadata}, formats::{json::JsonFormat, raw::RawFormat, raw_json::RawJsonFormat}, + event::{EventData, EventMetadata}, formats::{json::JsonFormat, nxlog::NxlogFormat, raw::RawFormat, raw_json::RawJsonFormat}, }; @@ -91,6 +91,7 @@ pub fn get_formatter(format :&SubscriptionOutputFormat) -> Box match format { SubscriptionOutputFormat::Json => Box::new(JsonFormat), SubscriptionOutputFormat::Raw => Box::new(RawFormat), - SubscriptionOutputFormat::RawJson => Box::new(RawJsonFormat) + SubscriptionOutputFormat::RawJson => Box::new(RawJsonFormat), + SubscriptionOutputFormat::Nxlog => Box::new(NxlogFormat) } } \ No newline at end of file