From 4b45802bf71ea1d5f3c1794619239a86d5389b60 Mon Sep 17 00:00:00 2001 From: argenis de la rosa Date: Wed, 4 Mar 2026 04:18:24 -0500 Subject: [PATCH] fix(audit): initialize log file when audit logging is enabled --- src/security/audit.rs | 52 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/security/audit.rs b/src/security/audit.rs index 816ecc787..d090a1ad8 100644 --- a/src/security/audit.rs +++ b/src/security/audit.rs @@ -166,6 +166,9 @@ impl AuditLogger { /// Create a new audit logger pub fn new(config: AuditConfig, zeroclaw_dir: PathBuf) -> Result { let log_path = zeroclaw_dir.join(&config.log_path); + if config.enabled { + initialize_audit_log_file(&log_path)?; + } Ok(Self { log_path, config, @@ -182,6 +185,8 @@ impl AuditLogger { // Check log size and rotate if needed self.rotate_if_needed()?; + initialize_audit_log_file(&self.log_path)?; + // Serialize and write let line = serde_json::to_string(event)?; let mut file = OpenOptions::new() @@ -258,6 +263,20 @@ impl AuditLogger { } } +fn initialize_audit_log_file(log_path: &std::path::Path) -> Result<()> { + if let Some(parent) = log_path.parent() { + if !parent.as_os_str().is_empty() { + std::fs::create_dir_all(parent)?; + } + } + + let _ = OpenOptions::new() + .create(true) + .append(true) + .open(log_path)?; + Ok(()) +} + #[cfg(test)] mod tests { use super::*; @@ -333,6 +352,39 @@ mod tests { Ok(()) } + #[test] + fn audit_logger_enabled_creates_file_on_init() -> Result<()> { + let tmp = TempDir::new()?; + let config = AuditConfig { + enabled: true, + ..Default::default() + }; + + let _logger = AuditLogger::new(config, tmp.path().to_path_buf())?; + assert!( + tmp.path().join("audit.log").exists(), + "audit log file should be created when audit logging is enabled" + ); + Ok(()) + } + + #[test] + fn audit_logger_enabled_creates_parent_directories() -> Result<()> { + let tmp = TempDir::new()?; + let config = AuditConfig { + enabled: true, + log_path: "logs/security/audit.log".to_string(), + ..Default::default() + }; + + let _logger = AuditLogger::new(config, tmp.path().to_path_buf())?; + assert!( + tmp.path().join("logs/security/audit.log").exists(), + "audit logger should create nested directories for configured log path" + ); + Ok(()) + } + // ── §8.1 Log rotation tests ───────────────────────────── #[tokio::test]