Make auditlog log

This commit is contained in:
Nadja Reitzenstein 2022-03-20 22:46:04 +01:00
parent c402c71abc
commit 3eab5b8702
6 changed files with 51 additions and 9 deletions

View File

@ -2,33 +2,41 @@ use std::fs::{File, OpenOptions};
use std::io; use std::io;
use std::io::{LineWriter, Write}; use std::io::{LineWriter, Write};
use std::sync::Mutex; use std::sync::Mutex;
use once_cell::sync::OnceCell;
use crate::Config; use crate::Config;
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
use serde_json::Serializer; use serde_json::Serializer;
pub static AUDIT: OnceCell<AuditLog> = OnceCell::new();
#[derive(Debug)] #[derive(Debug)]
pub struct AuditLog { pub struct AuditLog {
writer: Mutex<LineWriter<File>>, writer: Mutex<LineWriter<File>>,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuditLogLine { pub struct AuditLogLine<'a> {
timestamp: i64, timestamp: i64,
machine: String, machine: &'a str,
state: String, state: &'a str,
} }
impl AuditLog { impl AuditLog {
pub fn new(config: &Config) -> io::Result<Self> { pub fn new(config: &Config) -> io::Result<&'static Self> {
AUDIT.get_or_try_init(|| {
tracing::debug!(path = %config.auditlog_path.display(), "Initializing audit log");
let fd = OpenOptions::new().create(true).append(true).open(&config.auditlog_path)?; let fd = OpenOptions::new().create(true).append(true).open(&config.auditlog_path)?;
let writer = Mutex::new(LineWriter::new(fd)); let writer = Mutex::new(LineWriter::new(fd));
Ok(Self { writer }) Ok(Self { writer })
})
} }
pub fn log(&self, machine: &str, state: &str) -> io::Result<()> { pub fn log(&self, machine: &str, state: &str) -> io::Result<()> {
let timestamp = chrono::Utc::now().timestamp(); let timestamp = chrono::Utc::now().timestamp();
let line = AuditLogLine { timestamp, machine: machine.to_string(), state: state.to_string() }; let line = AuditLogLine { timestamp, machine, state };
tracing::debug!(?line, "writing audit log line");
let mut guard = self.writer.lock().unwrap(); let mut guard = self.writer.lock().unwrap();
let mut writer: &mut LineWriter<File> = &mut *guard; let mut writer: &mut LineWriter<File> = &mut *guard;

View File

@ -50,6 +50,7 @@ use once_cell::sync::OnceCell;
use signal_hook::consts::signal::*; use signal_hook::consts::signal::*;
use executor::pool::Executor; use executor::pool::Executor;
use crate::audit::AuditLog;
use crate::authentication::AuthenticationHandle; use crate::authentication::AuthenticationHandle;
use crate::authorization::roles::Roles; use crate::authorization::roles::Roles;
use crate::capnp::APIServer; use crate::capnp::APIServer;
@ -93,6 +94,8 @@ impl Diflouroborane {
let users = Users::new(env.clone()).context("Failed to open users DB file")?; let users = Users::new(env.clone()).context("Failed to open users DB file")?;
let roles = Roles::new(config.roles.clone()); let roles = Roles::new(config.roles.clone());
let _audit_log = AuditLog::new(&config).context("Failed to initialize audit log")?;
let resources = ResourcesHandle::new(config.machines.iter().map(|(id, desc)| { let resources = ResourcesHandle::new(config.machines.iter().map(|(id, desc)| {
Resource::new(Arc::new(resources::Inner::new(id.to_string(), statedb.clone(), desc.clone()))) Resource::new(Arc::new(resources::Inner::new(id.to_string(), statedb.clone(), desc.clone())))
})); }));

View File

@ -7,6 +7,7 @@ use rkyv::{Archived, Deserialize};
use rkyv::option::ArchivedOption; use rkyv::option::ArchivedOption;
use rkyv::ser::Serializer; use rkyv::ser::Serializer;
use rkyv::ser::serializers::AllocSerializer; use rkyv::ser::serializers::AllocSerializer;
use crate::audit::AUDIT;
use crate::authorization::permissions::PrivilegesBuf; use crate::authorization::permissions::PrivilegesBuf;
use crate::config::MachineDescription; use crate::config::MachineDescription;
use crate::db::ArchivedValue; use crate::db::ArchivedValue;
@ -75,6 +76,8 @@ impl Inner {
self.db.put(&self.id.as_bytes(), &state).unwrap(); self.db.put(&self.id.as_bytes(), &state).unwrap();
tracing::trace!("Updated DB, sending update signal"); tracing::trace!("Updated DB, sending update signal");
AUDIT.get().unwrap().log(self.id.as_str(), &format!("{}", state));
self.signal.set(state); self.signal.set(state);
tracing::trace!("Sent update signal"); tracing::trace!("Sent update signal");
} }

View File

@ -1,4 +1,5 @@
use std::fmt;
use std::fmt::{Write, write};
use crate::utils::oid::ObjectIdentifier; use crate::utils::oid::ObjectIdentifier;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use rkyv::{Archive, Archived, Deserialize, Infallible}; use rkyv::{Archive, Archived, Deserialize, Infallible};
@ -57,6 +58,19 @@ pub struct MachineState {
pub previous: Option<UserRef>, pub previous: Option<UserRef>,
} }
impl fmt::Display for ArchivedMachineState {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.state {
ArchivedStatus::Free => f.write_str("free"),
ArchivedStatus::InUse(user) => write!(f, "inuse {}", user),
ArchivedStatus::ToCheck(user) => write!(f, "tocheck {}", user),
ArchivedStatus::Blocked(user) => write!(f, "blocked {}", user),
ArchivedStatus::Disabled => f.write_str("disabled"),
ArchivedStatus::Reserved(user) => write!(f, "reserved {}", user),
}
}
}
impl MachineState { impl MachineState {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {

View File

@ -31,6 +31,7 @@ pub struct State {
pub inner: MachineState, pub inner: MachineState,
} }
impl fmt::Debug for State { impl fmt::Debug for State {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut sf = f.debug_struct("State"); let mut sf = f.debug_struct("State");
@ -42,6 +43,12 @@ impl fmt::Debug for State {
} }
} }
impl fmt::Display for ArchivedState {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Display::fmt(&self.inner, f)
}
}
impl serde::Serialize for State { impl serde::Serialize for State {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: serde::Serializer where S: serde::Serializer

View File

@ -3,6 +3,7 @@ use lmdb::Environment;
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use rkyv::{Archive, Deserialize, Infallible, Serialize}; use rkyv::{Archive, Deserialize, Infallible, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt::{Display, Formatter, Write};
use std::ops::Deref; use std::ops::Deref;
use std::path::Path; use std::path::Path;
use std::sync::Arc; use std::sync::Arc;
@ -41,6 +42,12 @@ impl PartialEq<UserRef> for ArchivedUserRef {
} }
} }
impl Display for ArchivedUserRef {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str(self.id.as_str())
}
}
impl UserRef { impl UserRef {
pub fn new(id: String) -> Self { pub fn new(id: String) -> Self {
UserRef { id } UserRef { id }