diff --git a/CHANGELOG-Japanese.md b/CHANGELOG-Japanese.md index 17e80277a..3e970efb0 100644 --- a/CHANGELOG-Japanese.md +++ b/CHANGELOG-Japanese.md @@ -8,6 +8,10 @@ - `expand`修飾子が入っているルールで使用されるプレースホルダー名を出力する`expand-list`コマンドを追加した。(#1513) (@fukuseket) - `expand`フィールド修飾子に対応した。 (#1434) (@fukusuket) +**改善:** + +- `log-metrics`コマンドにファイルサイズを追加した。 (#1528) (@fukusuket) + **バグ修正:** - レコードIDが出力されるとき、`csv-timeline`によるソートが完璧に行われなかった。 (#1519) (@fukusuket) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2496f5449..cf40f486c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ - New `expand-list` command to output placeholder names used for rules with the `expand` modifier. (#1513) (@fukuseket) - Support for `expand` field modifiers. (#1434) (@fukusuket) +**Enhancements:** + +- Log file size added to `log-metrics` command. (#1528) (@fukusuket) + **Bug Fixes:** - Sorting with `csv-timeline` was not done perfectly when record IDs were outputted. (#1519) (@fukusuket) diff --git a/src/detections/utils.rs b/src/detections/utils.rs index 7193cc52b..a1cf5d5d1 100644 --- a/src/detections/utils.rs +++ b/src/detections/utils.rs @@ -33,7 +33,7 @@ use crate::options::htmlreport; use super::configs::{EventKeyAliasConfig, OutputOption, STORED_EKEY_ALIAS}; use super::detection::EvtxRecordInfo; -use super::message::AlertMessage; +use super::message::{AlertMessage, ERROR_LOG_STACK}; use rust_embed::Embed; #[derive(Embed)] @@ -810,6 +810,24 @@ pub fn remove_sp_char(record_value: CompactString) -> CompactString { newline_replaced_cs.trim().into() } +pub fn get_file_size(file_path: &Path, verbose_flag: bool, quiet_errors_flag: bool) -> u64 { + match fs::metadata(file_path) { + Ok(res) => res.len(), + Err(err) => { + if verbose_flag { + AlertMessage::warn(&err.to_string()).ok(); + } + if !quiet_errors_flag { + ERROR_LOG_STACK + .lock() + .unwrap() + .push(format!("[WARN] {err}")); + } + 0 + } + } +} + #[cfg(test)] mod tests { use std::path::Path; diff --git a/src/main.rs b/src/main.rs index dab17a2f3..d782e425c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -42,7 +42,8 @@ use hayabusa::detections::message::{AlertMessage, DetectInfo, ERROR_LOG_STACK}; use hayabusa::detections::rule::{get_detection_keys, RuleNode}; use hayabusa::detections::utils; use hayabusa::detections::utils::{ - check_setting_path, get_writable_color, output_and_data_stack_for_html, output_profile_name, + check_setting_path, get_file_size, get_writable_color, output_and_data_stack_for_html, + output_profile_name, }; use hayabusa::filter::create_channel_filter; use hayabusa::options::htmlreport::{self, HTML_REPORTER}; @@ -1263,7 +1264,11 @@ impl App { .ok(); let mut total_file_size = ByteSize::b(0); for file_path in &evtx_files { - let file_size = Self::get_file_size(file_path, stored_static); + let file_size = get_file_size( + file_path, + stored_static.verbose_flag, + stored_static.quiet_errors_flag, + ); total_file_size += ByteSize::b(file_size); } write_color_buffer( @@ -1853,7 +1858,11 @@ impl App { let mut afterfact_writer = afterfact::init_writer(stored_static); for evtx_file in evtx_files { if is_show_progress { - let size = Self::get_file_size(&evtx_file, stored_static); + let size = get_file_size( + &evtx_file, + stored_static.verbose_flag, + stored_static.quiet_errors_flag, + ); let file_size = ByteSize::b(size); let pb_msg = format!( "{:?} ({})", @@ -2767,24 +2776,6 @@ impl App { _ => true, } } - - fn get_file_size(file_path: &Path, stored_static: &StoredStatic) -> u64 { - match fs::metadata(file_path) { - Ok(res) => res.len(), - Err(err) => { - if stored_static.verbose_flag { - AlertMessage::warn(&err.to_string()).ok(); - } - if !stored_static.quiet_errors_flag { - ERROR_LOG_STACK - .lock() - .unwrap() - .push(format!("[WARN] {err}")); - } - 0 - } - } - } } #[cfg(test)] diff --git a/src/timeline/log_metrics.rs b/src/timeline/log_metrics.rs index f1f54ad89..6807a82f1 100644 --- a/src/timeline/log_metrics.rs +++ b/src/timeline/log_metrics.rs @@ -8,6 +8,7 @@ use std::collections::HashSet; #[derive(Default, Debug, Clone)] pub struct LogMetrics { pub filename: String, + pub file_size: String, pub computers: HashSet, pub event_count: usize, pub first_timestamp: Option>, @@ -17,9 +18,10 @@ pub struct LogMetrics { } impl LogMetrics { - pub fn new(filename: &str) -> Self { + pub fn new(filename: &str, file_size: String) -> Self { Self { filename: filename.to_string(), + file_size, ..Default::default() } } diff --git a/src/timeline/metrics.rs b/src/timeline/metrics.rs index e51334e6f..b79154a56 100644 --- a/src/timeline/metrics.rs +++ b/src/timeline/metrics.rs @@ -1,5 +1,5 @@ use crate::detections::message::ERROR_LOG_STACK; -use crate::detections::utils::get_serde_number_to_string; +use crate::detections::utils::{get_file_size, get_serde_number_to_string}; use crate::detections::{ configs::{EventKeyAliasConfig, StoredStatic}, detection::EvtxRecordInfo, @@ -8,6 +8,7 @@ use crate::detections::{ }; use crate::timeline::log_metrics::LogMetrics; use crate::timeline::metrics::Channel::{RdsGtw, RdsLsm, Sec}; +use bytesize::ByteSize; use chrono::{DateTime, NaiveDate, NaiveDateTime, Utc}; use compact_str::CompactString; use hashbrown::{HashMap, HashSet}; @@ -96,13 +97,20 @@ impl EventMetrics { } self.stats_time_cnt(records, stored_static); - let filename = Path::new(self.filepath.as_str()) + let path = Path::new(self.filepath.as_str()); + let file_name = path .file_name() .unwrap_or_default() .to_str() .unwrap_or_default(); + let file_size = get_file_size( + path, + stored_static.verbose_flag, + stored_static.quiet_errors_flag, + ); + let file_size = ByteSize::b(file_size).to_string(); if let Some(existing_lm) = self.stats_logfile.iter_mut().find(|lm| { - lm.filename == filename + lm.filename == file_name && lm.computers.contains( get_event_value_as_string( "Computer", @@ -115,7 +123,7 @@ impl EventMetrics { }) { existing_lm.update(records, stored_static); } else { - let mut lm = LogMetrics::new(filename); + let mut lm = LogMetrics::new(file_name, file_size); lm.update(records, stored_static); self.stats_logfile.push(lm); } diff --git a/src/timeline/timelines.rs b/src/timeline/timelines.rs index 9e6e25304..63d271296 100644 --- a/src/timeline/timelines.rs +++ b/src/timeline/timelines.rs @@ -606,6 +606,7 @@ impl Timeline { "Last Timestamp", "Channels", "Providers", + "Size", ]; if let Some(path) = &opt.output { let file = File::create(path).expect("Failed to create output file"); @@ -632,6 +633,7 @@ impl Timeline { Cell::new(r[4].to_string()), Cell::new(r[5].to_string()), Cell::new(r[6].to_string()), + Cell::new(r[7].to_string()), ]); } } @@ -670,7 +672,7 @@ impl Timeline { rec: &LogMetrics, stored_static: &StoredStatic, sep: &str, - ) -> Option<[String; 7]> { + ) -> Option<[String; 8]> { let include_computer = &stored_static.include_computer; let exclude_computer = &stored_static.exclude_computer; if !include_computer.is_empty() @@ -730,6 +732,7 @@ impl Timeline { .into(), ab_ch.iter().sorted().join(sep), ab_provider.iter().sorted().join(sep), + rec.file_size.to_string(), ]) } }