Skip to content

Commit

Permalink
fix #73: [kunai] implement log rotation
Browse files Browse the repository at this point in the history
  • Loading branch information
qjerome committed Jul 18, 2024
1 parent 0a20bd4 commit c10d632
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 17 deletions.
76 changes: 67 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions kunai/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ lazy_static = "1.4.0"
serde_json = "1.0.108"
uuid = { version = "1.6.1", features = ["serde", "v5"] }
object = { version = "0.34.0", features = ["elf"] }
huby = { version = "0.1", features = ["serde"] }
firo = { version = "0.1" }


[[bin]]
name = "kunai"
Expand Down
90 changes: 82 additions & 8 deletions kunai/src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,11 @@ use tokio::sync::mpsc::error::SendError;
use std::borrow::Cow;
use std::collections::{HashMap, HashSet, VecDeque};

use std::fs::{self, File};
use std::fs::{self, DirBuilder, File};
use std::io::{self, BufRead, Write};
use std::net::IpAddr;

use std::os::unix::fs::{DirBuilderExt, OpenOptionsExt};
use std::path::{Path, PathBuf};
use std::str::FromStr;

Expand Down Expand Up @@ -125,6 +126,49 @@ impl SystemInfo {
}
}

pub enum Output {
Stdout(std::io::Stdout),
Stderr(std::io::Stderr),
// variant too big, boxing suggested by clippy
File(Box<firo::File>),
}

impl Output {
#[inline(always)]
fn stdout() -> Self {
Self::Stdout(std::io::stdout())
}

#[inline(always)]
fn stderr() -> Self {
Self::Stderr(std::io::stderr())
}
}

impl From<firo::File> for Output {
fn from(value: firo::File) -> Self {
Self::File(Box::new(value))
}
}

impl io::Write for Output {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
match self {
Self::Stdout(o) => o.write(buf),
Self::Stderr(o) => o.write(buf),
Self::File(o) => o.write(buf),
}
}

fn flush(&mut self) -> io::Result<()> {
match self {
Self::Stdout(o) => o.flush(),
Self::Stderr(o) => o.flush(),
Self::File(o) => o.flush(),
}
}
}

struct EventConsumer {
system_info: SystemInfo,
engine: gene::Engine,
Expand All @@ -133,17 +177,51 @@ struct EventConsumer {
cache: cache::Cache,
tasks: HashMap<TaskKey, Task>,
resolved: HashMap<IpAddr, String>,
output: std::fs::File,
output: Output,
}

impl EventConsumer {
pub fn with_config(config: Config) -> anyhow::Result<Self> {
fn prepare_output(config: &Config) -> anyhow::Result<Output> {
let output = match &config.output.as_str() {
&"stdout" => String::from("/dev/stdout"),
&"stderr" => String::from("/dev/stderr"),
v => v.to_string(),
};

let out = match output.as_str() {
"/dev/stdout" => Output::stdout(),
"/dev/stderr" => Output::stderr(),
v => {
let path = PathBuf::from(v);

if let Some(parent) = path.parent() {
if !parent.exists() {
// we only create parent directory
DirBuilder::new().mode(0o700).create(parent).map_err(|e| {
anyhow!("failed to create output directory {parent:?}: {e}")
})?;
}
}

match config.output_settings.as_ref() {
Some(s) => firo::OpenOptions::new()
.mode(0o600)
.max_size(s.max_size)
.trigger(s.rotate_size.into())
.compression(firo::Compression::Gzip)
.create_append(v)?
.into(),
None => firo::OpenOptions::new()
.mode(0o600)
.create_append(v)?
.into(),
}
}
};
Ok(out)
}

pub fn with_config(config: Config) -> anyhow::Result<Self> {
// building up system information
let system_info = SystemInfo::from_sys()?.with_host_uuid(
config
Expand All @@ -159,10 +237,7 @@ impl EventConsumer {
cache: Cache::with_max_entries(10000),
tasks: HashMap::new(),
resolved: HashMap::new(),
output: std::fs::OpenOptions::new()
.append(true)
.create(true)
.open(output)?,
output: Self::prepare_output(&config)?,
};

// loading rules in the engine
Expand Down Expand Up @@ -1786,7 +1861,6 @@ fn load_and_attach_bpf(kernel: KernelVersion, bpf: &mut Bpf) -> anyhow::Result<P
p.enable();
}


if !p.enable {
warn!("{} probe has been disabled", p.name);
continue;
Expand Down
9 changes: 9 additions & 0 deletions kunai/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use core::str::FromStr;
use huby::ByteSize;
use kunai_common::{
bpf_events,
config::{BpfConfig, Filter, Loader},
Expand Down Expand Up @@ -38,11 +39,18 @@ impl Event {
}
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct FileSettings {
pub rotate_size: ByteSize,
pub max_size: ByteSize,
}

/// Kunai configuration structure to be used in userland
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Config {
host_uuid: Option<uuid::Uuid>,
pub output: String,
pub output_settings: Option<FileSettings>,
pub max_buffered_events: u16,
pub send_data_min_len: Option<u64>,
pub rules: Vec<String>,
Expand All @@ -68,6 +76,7 @@ impl Default for Config {
Self {
host_uuid: None,
output: "/dev/stdout".into(),
output_settings: None,
max_buffered_events: DEFAULT_MAX_BUFFERED_EVENTS,
send_data_min_len: None,
rules: vec![],
Expand Down

0 comments on commit c10d632

Please sign in to comment.