From 76579100e227aa19878df0f98d398c3514a6b22b Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Fri, 12 Dec 2025 16:34:24 +0900 Subject: [PATCH 1/3] log-parser: Support configuration file Signed-off-by: Daiki Ueno --- Cargo.lock | 1 + GNUmakefile | 1 + dist/conf/log-parser.conf | 1 + log-parser/Cargo.toml | 1 + log-parser/src/config.rs | 89 ++++++++++++++++++++++++++++++++++++ log-parser/src/log_parser.rs | 18 +++----- 6 files changed, 99 insertions(+), 12 deletions(-) create mode 100644 dist/conf/log-parser.conf create mode 100644 log-parser/src/config.rs diff --git a/Cargo.lock b/Cargo.lock index 2bba65e..0738553 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -424,6 +424,7 @@ dependencies = [ "serde_cbor", "serde_json", "serde_with", + "toml", ] [[package]] diff --git a/GNUmakefile b/GNUmakefile index 23316ce..bf412ae 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -25,6 +25,7 @@ conffiles = \ dist/conf/agent.conf \ dist/conf/client.conf \ dist/conf/event-broker.conf \ + dist/conf/log-parser.conf \ dist/conf/monitor.conf .PHONY: all diff --git a/dist/conf/log-parser.conf b/dist/conf/log-parser.conf new file mode 100644 index 0000000..fb4fe91 --- /dev/null +++ b/dist/conf/log-parser.conf @@ -0,0 +1 @@ +# log_file = "/var/log/crypto-auditing/audit.cborseq" diff --git a/log-parser/Cargo.toml b/log-parser/Cargo.toml index f8cf0b3..cd19280 100644 --- a/log-parser/Cargo.toml +++ b/log-parser/Cargo.toml @@ -15,6 +15,7 @@ serde.workspace = true serde_cbor.workspace = true serde_json.workspace = true serde_with = { workspace = true, features = ["hex"] } +toml.workspace = true [[bin]] name = "crau-log-parser" diff --git a/log-parser/src/config.rs b/log-parser/src/config.rs new file mode 100644 index 0000000..caaf313 --- /dev/null +++ b/log-parser/src/config.rs @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (C) 2022-2023 The crypto-auditing developers. + +use anyhow::{Context as _, Result, anyhow}; +use clap::{ArgMatches, arg, command, parser::ValueSource, value_parser}; +use std::fs; +use std::path::{Path, PathBuf}; +use std::str::FromStr; +use toml::{Table, Value}; + +const CONFIG: &str = "/etc/crypto-auditing/log-parser.conf"; +const LOG: &str = "/var/log/crypto-auditing/audit.cborseq"; + +#[derive(Debug)] +pub struct Config { + /// Path to output log file + pub log_file: PathBuf, +} + +impl Default for Config { + fn default() -> Self { + Self { + log_file: PathBuf::from(LOG), + } + } +} + +impl Config { + pub fn new() -> Result { + let mut config = Config::default(); + + let matches = command!() + .arg( + arg!( + -c --config "Path to configuration file" + ) + .required(false) + .value_parser(value_parser!(PathBuf)), + ) + .arg( + arg!( + --"log-file" "Path to output log file" + ) + .required(false) + .value_parser(value_parser!(PathBuf)) + .default_value("audit.cborseq"), + ) + .get_matches(); + + if let Some(config_file) = matches.get_one::("config") { + config.merge_config_file(config_file)?; + } else if Path::new(CONFIG).exists() { + config.merge_config_file(CONFIG)?; + } + + config.merge_arg_matches(&matches)?; + + Ok(config) + } + + fn merge_config_file(&mut self, file: impl AsRef) -> Result<()> { + let s = fs::read_to_string(file.as_ref()) + .with_context(|| format!("unable to read config file `{}`", file.as_ref().display()))?; + let config = Table::from_str(&s).with_context(|| { + format!("unable to parse config file `{}`", file.as_ref().display()) + })?; + + if let Some(value) = config.get("log_file") { + self.log_file = pathbuf_from_value(value)?; + } + + Ok(()) + } + + fn merge_arg_matches(&mut self, matches: &ArgMatches) -> Result<()> { + if let Some(ValueSource::CommandLine) = matches.value_source("log-file") { + self.log_file = matches.try_get_one::("log-file")?.unwrap().clone(); + } + + Ok(()) + } +} + +fn pathbuf_from_value(value: &Value) -> Result { + value + .as_str() + .ok_or_else(|| anyhow!("value must be string")) + .map(PathBuf::from) +} diff --git a/log-parser/src/log_parser.rs b/log-parser/src/log_parser.rs index 3b492df..4af42e9 100644 --- a/log-parser/src/log_parser.rs +++ b/log-parser/src/log_parser.rs @@ -2,23 +2,17 @@ // Copyright (C) 2022-2023 The crypto-auditing developers. use anyhow::{Context as _, Result}; -use clap::Parser; use crypto_auditing::types::{ContextTracker, EventGroup}; use serde_cbor::de::Deserializer; -use std::path::PathBuf; -#[derive(Parser)] -#[command(author, version, about, long_about = None)] -#[command(about = "Primary log parser for crypto-auditing")] -struct Cli { - /// Path to log file to parse - log_path: PathBuf, -} +mod config; fn main() -> Result<(), Box> { - let cli = Cli::parse(); - let log_file = std::fs::File::open(&cli.log_path) - .with_context(|| format!("unable to read file `{}`", cli.log_path.display()))?; + let config = config::Config::new()?; + + let log_file = std::fs::File::open(&config.log_file) + .with_context(|| format!("unable to read file `{}`", config.log_file.display()))?; + let mut tracker = ContextTracker::new(None); for group in Deserializer::from_reader(&log_file).into_iter::() { tracker.handle_event_group(&group?); From ba239de2579adbbfb935b629cf7f90c2a04657e3 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Fri, 12 Dec 2025 16:45:13 +0900 Subject: [PATCH 2/3] log-parser: Print output through pager if needed Signed-off-by: Daiki Ueno --- Cargo.lock | 34 +++++++++++++++++++++++++++++++++- log-parser/Cargo.toml | 1 + log-parser/src/log_parser.rs | 10 +++++++++- 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0738553..9e3f0c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -420,6 +420,7 @@ dependencies = [ "clap", "crypto-auditing", "hex", + "pager", "serde", "serde_cbor", "serde_json", @@ -536,6 +537,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "errno" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] + [[package]] name = "errno" version = "0.3.14" @@ -546,6 +558,16 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "fastrand" version = "2.3.0" @@ -1200,6 +1222,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "pager" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2599211a5c97fbbb1061d3dc751fa15f404927e4846e07c643287d6d1f462880" +dependencies = [ + "errno 0.2.8", + "libc", +] + [[package]] name = "pin-project" version = "1.1.10" @@ -1352,7 +1384,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" dependencies = [ "bitflags 2.10.0", - "errno", + "errno 0.3.14", "libc", "linux-raw-sys", "windows-sys 0.61.2", diff --git a/log-parser/Cargo.toml b/log-parser/Cargo.toml index cd19280..64e03f8 100644 --- a/log-parser/Cargo.toml +++ b/log-parser/Cargo.toml @@ -16,6 +16,7 @@ serde_cbor.workspace = true serde_json.workspace = true serde_with = { workspace = true, features = ["hex"] } toml.workspace = true +pager = "0.16" [[bin]] name = "crau-log-parser" diff --git a/log-parser/src/log_parser.rs b/log-parser/src/log_parser.rs index 4af42e9..57f1da0 100644 --- a/log-parser/src/log_parser.rs +++ b/log-parser/src/log_parser.rs @@ -3,12 +3,15 @@ use anyhow::{Context as _, Result}; use crypto_auditing::types::{ContextTracker, EventGroup}; +use pager::Pager; use serde_cbor::de::Deserializer; +use std::io::{self, Write}; mod config; fn main() -> Result<(), Box> { let config = config::Config::new()?; + Pager::new().skip_on_notty().setup(); let log_file = std::fs::File::open(&config.log_file) .with_context(|| format!("unable to read file `{}`", config.log_file.display()))?; @@ -18,6 +21,11 @@ fn main() -> Result<(), Box> { tracker.handle_event_group(&group?); } let root_contexts: Vec<_> = tracker.flush(None).into_iter().collect(); - println!("{}", serde_json::to_string_pretty(&root_contexts).unwrap()); + let content = serde_json::to_string_pretty(&root_contexts)?; + if let Err(e) = io::stdout().write_all(content.as_bytes()) { + if e.kind() != io::ErrorKind::BrokenPipe { + return Err(Box::new(e)); + } + } Ok(()) } From 48daefbddcb3cad5824f878cd33633c27b733942 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Fri, 12 Dec 2025 20:42:22 +0900 Subject: [PATCH 3/3] =?UTF-8?q?crau-log-parser=20=E2=86=92=20crau-query?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Daiki Ueno --- GNUmakefile | 4 ++-- dist/conf/{log-parser.conf => query.conf} | 0 log-parser/Cargo.toml | 4 ++-- log-parser/src/config.rs | 2 +- log-parser/src/{log_parser.rs => query.rs} | 0 5 files changed, 5 insertions(+), 5 deletions(-) rename dist/conf/{log-parser.conf => query.conf} (100%) rename log-parser/src/{log_parser.rs => query.rs} (100%) diff --git a/GNUmakefile b/GNUmakefile index bf412ae..e9dba9e 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -18,14 +18,14 @@ programs = \ ${TARGETDIR}/${PROFILE}/crau-agent \ ${TARGETDIR}/${PROFILE}/crau-client \ ${TARGETDIR}/${PROFILE}/crau-event-broker \ - ${TARGETDIR}/${PROFILE}/crau-log-parser \ + ${TARGETDIR}/${PROFILE}/crau-query \ ${TARGETDIR}/${PROFILE}/crau-monitor conffiles = \ dist/conf/agent.conf \ dist/conf/client.conf \ dist/conf/event-broker.conf \ - dist/conf/log-parser.conf \ + dist/conf/query.conf \ dist/conf/monitor.conf .PHONY: all diff --git a/dist/conf/log-parser.conf b/dist/conf/query.conf similarity index 100% rename from dist/conf/log-parser.conf rename to dist/conf/query.conf diff --git a/log-parser/Cargo.toml b/log-parser/Cargo.toml index 64e03f8..960c0b1 100644 --- a/log-parser/Cargo.toml +++ b/log-parser/Cargo.toml @@ -19,5 +19,5 @@ toml.workspace = true pager = "0.16" [[bin]] -name = "crau-log-parser" -path = "src/log_parser.rs" +name = "crau-query" +path = "src/query.rs" diff --git a/log-parser/src/config.rs b/log-parser/src/config.rs index caaf313..5e6ae1a 100644 --- a/log-parser/src/config.rs +++ b/log-parser/src/config.rs @@ -8,7 +8,7 @@ use std::path::{Path, PathBuf}; use std::str::FromStr; use toml::{Table, Value}; -const CONFIG: &str = "/etc/crypto-auditing/log-parser.conf"; +const CONFIG: &str = "/etc/crypto-auditing/query.conf"; const LOG: &str = "/var/log/crypto-auditing/audit.cborseq"; #[derive(Debug)] diff --git a/log-parser/src/log_parser.rs b/log-parser/src/query.rs similarity index 100% rename from log-parser/src/log_parser.rs rename to log-parser/src/query.rs