From fa3feea0da4f40ae6964385689d6cb2f238dd495 Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Sun, 25 Jun 2023 14:03:20 +0100 Subject: [PATCH] Add support for rotating audit logs --- flake.nix | 12 ++++++++++++ src/audit.rs | 29 ++++++++++++++++++++++------- src/main.rs | 19 ++++++++++++++++++- 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/flake.nix b/flake.nix index e267263..4d35e92 100644 --- a/flake.nix +++ b/flake.nix @@ -52,6 +52,7 @@ { Type = "exec"; ExecStart = "${self.defaultPackage."${system}"}/bin/pisshoff -c \"${conf}\""; + ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; Restart = "on-failure"; LogsDirectory = "pisshoff"; @@ -82,6 +83,17 @@ SystemCallFilter = [ "@system-service" "~@privileged" ]; }; }; + + services.logrotate.settings.pisshoff = { + files = "/var/log/pisshoff/audit.log"; + rotate = 31; + frequency = "daily"; + compress = true; + delaycompress = true; + missingok = true; + notifempty = true; + postrotate = "systemctl reload pisshoff"; + }; }; }; }); diff --git a/src/audit.rs b/src/audit.rs index 1f019e2..e2ae288 100644 --- a/src/audit.rs +++ b/src/audit.rs @@ -11,13 +11,15 @@ use time::OffsetDateTime; use tokio::{ fs::OpenOptions, io::{AsyncWriteExt, BufWriter}, + sync::watch, task::JoinHandle, }; -use tracing::debug; +use tracing::{debug, info}; use uuid::Uuid; pub fn start_audit_writer( config: Arc, + mut reload: watch::Receiver<()>, ) -> ( tokio::sync::mpsc::UnboundedSender, JoinHandle>, @@ -25,12 +27,16 @@ pub fn start_audit_writer( let (send, mut recv) = tokio::sync::mpsc::unbounded_channel(); let handle = tokio::spawn(async move { - let file = OpenOptions::default() - .create(true) - .append(true) - .open(&config.audit_output_file) - .await?; - let mut writer = BufWriter::new(file); + let open_writer = || async { + let file = OpenOptions::default() + .create(true) + .append(true) + .open(&config.audit_output_file) + .await?; + Ok::<_, std::io::Error>(BufWriter::new(file)) + }; + + let mut writer = open_writer().await?; let mut shutdown = false; loop { @@ -52,6 +58,15 @@ pub fn start_audit_writer( debug!("Flushing audits to disk"); writer.flush().await?; } + Ok(()) = reload.changed(), if !shutdown => { + info!("Flushing audits to disk"); + writer.flush().await?; + + info!("Reopening handle to log file"); + writer = open_writer().await?; + + info!("Successfully re-opened log file"); + } else => break, } } diff --git a/src/main.rs b/src/main.rs index 6ed62d2..09b9fa4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,7 @@ use clap::Parser; use futures::FutureExt; use std::sync::Arc; use thrussh::MethodSet; +use tokio::{signal::unix::SignalKind, sync::watch}; use tracing::{error, info}; use tracing_subscriber::EnvFilter; @@ -47,7 +48,9 @@ async fn run() -> anyhow::Result<()> { ..thrussh::server::Config::default() }); - let (audit_send, audit_handle) = audit::start_audit_writer(args.config.clone()); + let (reload_send, reload_recv) = watch::channel(()); + + let (audit_send, audit_handle) = audit::start_audit_writer(args.config.clone(), reload_recv); let mut audit_handle = audit_handle.fuse(); let server = Server::new(args.config.clone(), audit_send); @@ -55,9 +58,12 @@ async fn run() -> anyhow::Result<()> { let fut = thrussh::server::run(thrussh_config, &listen_address, server); + let reload_watcher = watch_for_reloads(reload_send); + tokio::select! { res = fut => res?, res = &mut audit_handle => res??, + res = reload_watcher => res?, _ = tokio::signal::ctrl_c() => { info!("Received ctrl-c, initiating shutdown"); } @@ -69,3 +75,14 @@ async fn run() -> anyhow::Result<()> { Ok(()) } + +async fn watch_for_reloads(send: watch::Sender<()>) -> Result<(), anyhow::Error> { + let mut signal = tokio::signal::unix::signal(SignalKind::hangup())?; + + while let Some(()) = signal.recv().await { + info!("Received SIGHUP, broadcasting reload"); + let _res = send.send(()); + } + + Ok(()) +} -- libgit2 1.7.2