use crate::security::siem::{SiemConfig, SiemEmitter};
use crate::Error;
use once_cell::sync::Lazy;
use std::sync::Arc;
use tokio::sync::RwLock;
use tracing::{debug, error};
static GLOBAL_SIEM_EMITTER: Lazy<Arc<RwLock<Option<SiemEmitter>>>> =
Lazy::new(|| Arc::new(RwLock::new(None)));
pub async fn init_global_siem_emitter(config: SiemConfig) -> Result<(), Error> {
let emitter = SiemEmitter::from_config(config).await?;
let mut global = GLOBAL_SIEM_EMITTER.write().await;
*global = Some(emitter);
debug!("Global SIEM emitter initialized");
Ok(())
}
pub async fn get_global_siem_emitter() -> Option<Arc<RwLock<Option<SiemEmitter>>>> {
Some(GLOBAL_SIEM_EMITTER.clone())
}
pub async fn emit_security_event(event: crate::security::events::SecurityEvent) {
let global = GLOBAL_SIEM_EMITTER.read().await;
if let Some(ref emitter) = *global {
if let Err(e) = emitter.emit(event).await {
error!("Failed to emit security event to SIEM: {}", e);
}
} else {
debug!("SIEM emitter not initialized, skipping event emission");
}
}
pub fn emit_security_event_async(event: crate::security::events::SecurityEvent) {
tokio::spawn(async move {
emit_security_event(event).await;
});
}
pub async fn is_siem_emitter_initialized() -> bool {
let global = GLOBAL_SIEM_EMITTER.read().await;
global.is_some()
}
#[cfg(test)]
mod tests {
use super::*;
use crate::security::events::SecurityEventType;
use crate::security::siem::SiemConfig;
#[tokio::test]
async fn test_init_global_siem_emitter() {
let config = SiemConfig::default();
assert!(init_global_siem_emitter(config).await.is_ok());
assert!(is_siem_emitter_initialized().await);
}
#[tokio::test]
async fn test_get_global_siem_emitter() {
let config = SiemConfig::default();
init_global_siem_emitter(config).await.unwrap();
let emitter_guard = get_global_siem_emitter().await;
assert!(emitter_guard.is_some());
let guard = emitter_guard.unwrap();
let emitter = guard.read().await;
assert!(emitter.is_some());
}
#[tokio::test]
async fn test_emit_security_event() {
let config = SiemConfig {
enabled: false, protocol: None,
destinations: vec![],
filters: None,
};
init_global_siem_emitter(config).await.unwrap();
let event =
crate::security::events::SecurityEvent::new(SecurityEventType::AuthSuccess, None, None);
emit_security_event(event).await;
}
}