fabaccess-bffh/bffhd/audit.rs

58 lines
1.5 KiB
Rust
Raw Normal View History

2022-05-05 15:50:44 +02:00
use once_cell::sync::OnceCell;
2022-03-11 23:00:02 +01:00
use std::fs::{File, OpenOptions};
use std::io;
use std::io::{LineWriter, Write};
use std::sync::Mutex;
use crate::Config;
2022-05-05 15:50:44 +02:00
use serde::{Deserialize, Serialize};
2022-03-11 23:00:02 +01:00
use serde_json::Serializer;
2022-03-20 22:46:04 +01:00
pub static AUDIT: OnceCell<AuditLog> = OnceCell::new();
2022-03-11 23:00:02 +01:00
#[derive(Debug)]
pub struct AuditLog {
writer: Mutex<LineWriter<File>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
2022-03-20 22:46:04 +01:00
pub struct AuditLogLine<'a> {
2022-03-11 23:00:02 +01:00
timestamp: i64,
2022-03-20 22:46:04 +01:00
machine: &'a str,
state: &'a str,
2022-03-11 23:00:02 +01:00
}
impl AuditLog {
2022-03-20 22:46:04 +01:00
pub fn new(config: &Config) -> io::Result<&'static Self> {
AUDIT.get_or_try_init(|| {
tracing::debug!(path = %config.auditlog_path.display(), "Initializing audit log");
2022-05-05 15:50:44 +02:00
let fd = OpenOptions::new()
.create(true)
.append(true)
.open(&config.auditlog_path)?;
2022-03-20 22:46:04 +01:00
let writer = Mutex::new(LineWriter::new(fd));
Ok(Self { writer })
})
2022-03-11 23:00:02 +01:00
}
2022-03-12 01:27:41 +01:00
pub fn log(&self, machine: &str, state: &str) -> io::Result<()> {
let timestamp = chrono::Utc::now().timestamp();
2022-05-05 15:50:44 +02:00
let line = AuditLogLine {
timestamp,
machine,
state,
};
2022-03-20 22:46:04 +01:00
tracing::debug!(?line, "writing audit log line");
2022-03-11 23:00:02 +01:00
let mut guard = self.writer.lock().unwrap();
let mut writer: &mut LineWriter<File> = &mut *guard;
let mut ser = Serializer::new(&mut writer);
2022-05-05 15:50:44 +02:00
line.serialize(&mut ser)
.expect("failed to serialize audit log line");
2022-03-11 23:00:02 +01:00
writer.write("\n".as_bytes())?;
Ok(())
}
}