output saving results message (#563)
* added Results Summary title #561 * added results message when output option is enabled. #561 * version number update * added newline * removed newline * tuned output #561 * fixed bug that console output table header color is same with 1st row color #561 * cargo fmt
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
- ロゴの色を変更した (#537) (@hitenkoku)
|
||||
- Channelの列にchannel_abbrevations.txtに記載されていないチャンネルも表示するようにした。(#553) (@hitenkoku)
|
||||
- `Ignored rules`として集計されていた`Exclude rules`、`Noisy rules`、`Deprecated rules`に分けて表示するようにした。 (#556) (@hitenkoku)
|
||||
- `output`オプションが指定されているときに、ファイル出力中のメッセージを表示するようにした。 (#561) (@hitenkoku)
|
||||
|
||||
**バグ修正:**
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
- Changed logo color. (#537) (@hitenkoku)
|
||||
- Display the original `Channel` name when not specified in `channel_abbrevations.txt`. (#553) (@hitenkoku)
|
||||
- Display separately `Ignored rules` to `Exclude rules`, `Noisy rules`, and `Deprecated rules`. (#556) (@hitenkoku)
|
||||
- Display results messge when `output` option is set. (#561) (@hitenkoku)
|
||||
|
||||
**Bug Fixes:**
|
||||
|
||||
|
||||
4
Cargo.lock
generated
4
Cargo.lock
generated
@@ -935,9 +935,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hayabusa"
|
||||
version = "1.3.0-dev"
|
||||
version = "1.3.0"
|
||||
dependencies = [
|
||||
"base64 0.13.0",
|
||||
"base64 0.10.1",
|
||||
"bytesize",
|
||||
"chrono",
|
||||
"clap 2.34.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "hayabusa"
|
||||
version = "1.3.0-dev"
|
||||
version = "1.3.0"
|
||||
authors = ["Yamato Security @SecurityYamato"]
|
||||
edition = "2021"
|
||||
|
||||
|
||||
@@ -195,9 +195,10 @@ fn emit_csv<W: std::io::Write>(
|
||||
) -> io::Result<()> {
|
||||
let disp_wtr = BufferWriter::stdout(ColorChoice::Always);
|
||||
let mut disp_wtr_buf = disp_wtr.buffer();
|
||||
|
||||
let mut wtr = csv::WriterBuilder::new().from_writer(writer);
|
||||
|
||||
disp_wtr_buf.set_color(ColorSpec::new().set_fg(None)).ok();
|
||||
|
||||
let messages = print::MESSAGES.lock().unwrap();
|
||||
// level is devided by "Critical","High","Medium","Low","Informational","Undefined".
|
||||
let mut total_detect_counts_by_level: Vec<u128> = vec![0; 6];
|
||||
@@ -222,8 +223,9 @@ fn emit_csv<W: std::io::Write>(
|
||||
detect_counts_by_date_and_level.insert(level_init.to_string(), HashMap::new());
|
||||
detect_counts_by_computer_and_level.insert(level_init.to_string(), HashMap::new());
|
||||
}
|
||||
|
||||
println!();
|
||||
if displayflag {
|
||||
println!();
|
||||
}
|
||||
let mut timestamps: Vec<i64> = Vec::new();
|
||||
let mut plus_header = true;
|
||||
let mut detected_record_idset: HashSet<String> = HashSet::new();
|
||||
@@ -263,6 +265,11 @@ fn emit_csv<W: std::io::Write>(
|
||||
record_i_d: record_id.as_deref(),
|
||||
};
|
||||
|
||||
//ヘッダーのみを出力
|
||||
if plus_header {
|
||||
write!(disp_wtr_buf, "{}", _get_serialized_disp_output(None)).ok();
|
||||
plus_header = false;
|
||||
}
|
||||
disp_wtr_buf
|
||||
.set_color(
|
||||
ColorSpec::new().set_fg(_get_output_color(&color_map, &detect_info.level)),
|
||||
@@ -271,10 +278,9 @@ fn emit_csv<W: std::io::Write>(
|
||||
write!(
|
||||
disp_wtr_buf,
|
||||
"{}",
|
||||
_get_serialized_disp_output(dispformat, plus_header)
|
||||
_get_serialized_disp_output(Some(dispformat))
|
||||
)
|
||||
.ok();
|
||||
plus_header = false;
|
||||
} else {
|
||||
// csv output format
|
||||
wtr.serialize(CsvFormat {
|
||||
@@ -333,10 +339,15 @@ fn emit_csv<W: std::io::Write>(
|
||||
}
|
||||
if displayflag {
|
||||
disp_wtr.print(&disp_wtr_buf)?;
|
||||
println!();
|
||||
} else {
|
||||
wtr.flush()?;
|
||||
}
|
||||
println!();
|
||||
|
||||
disp_wtr_buf.clear();
|
||||
disp_wtr_buf.set_color(ColorSpec::new().set_fg(None)).ok();
|
||||
writeln!(disp_wtr_buf, "Results Summary:").ok();
|
||||
disp_wtr.print(&disp_wtr_buf).ok();
|
||||
|
||||
let size = terminal_size();
|
||||
let terminal_width = match size {
|
||||
@@ -393,15 +404,18 @@ enum ColPos {
|
||||
Other,
|
||||
}
|
||||
|
||||
fn _get_serialized_disp_output(dispformat: DisplayFormat, plus_header: bool) -> String {
|
||||
fn _get_serialized_disp_output(dispformat: Option<DisplayFormat>) -> String {
|
||||
if dispformat.is_none() {
|
||||
return "Timestamp|Computer|Channel|EventID|Level|RuleTitle|Details|RecordID|RecordInformation\n".to_string();
|
||||
}
|
||||
let mut disp_serializer = csv::WriterBuilder::new()
|
||||
.double_quote(false)
|
||||
.quote_style(QuoteStyle::Never)
|
||||
.delimiter(b'|')
|
||||
.has_headers(plus_header)
|
||||
.has_headers(false)
|
||||
.from_writer(vec![]);
|
||||
|
||||
disp_serializer.serialize(dispformat).ok();
|
||||
disp_serializer.serialize(dispformat.unwrap()).ok();
|
||||
|
||||
String::from_utf8(disp_serializer.into_inner().unwrap_or_default()).unwrap_or_default()
|
||||
}
|
||||
@@ -737,39 +751,19 @@ mod tests {
|
||||
+ "|"
|
||||
+ test_recinfo
|
||||
+ "\n";
|
||||
let expect_with_header = expect_header.to_string() + &expect_no_header;
|
||||
assert_eq!(_get_serialized_disp_output(None,), expect_header);
|
||||
assert_eq!(
|
||||
_get_serialized_disp_output(
|
||||
DisplayFormat {
|
||||
timestamp: &format_time(&test_timestamp),
|
||||
level: test_level,
|
||||
computer: test_computername,
|
||||
event_i_d: test_eventid,
|
||||
channel: test_channel,
|
||||
rule_title: test_title,
|
||||
details: output,
|
||||
record_information: Some(test_recinfo),
|
||||
record_i_d: Some(test_recid),
|
||||
},
|
||||
true
|
||||
),
|
||||
expect_with_header
|
||||
);
|
||||
assert_eq!(
|
||||
_get_serialized_disp_output(
|
||||
DisplayFormat {
|
||||
timestamp: &format_time(&test_timestamp),
|
||||
level: test_level,
|
||||
computer: test_computername,
|
||||
event_i_d: test_eventid,
|
||||
channel: test_channel,
|
||||
rule_title: test_title,
|
||||
details: output,
|
||||
record_information: Some(test_recinfo),
|
||||
record_i_d: Some(test_recid),
|
||||
},
|
||||
false
|
||||
),
|
||||
_get_serialized_disp_output(Some(DisplayFormat {
|
||||
timestamp: &format_time(&test_timestamp),
|
||||
level: test_level,
|
||||
computer: test_computername,
|
||||
event_i_d: test_eventid,
|
||||
channel: test_channel,
|
||||
rule_title: test_title,
|
||||
details: output,
|
||||
record_information: Some(test_recinfo),
|
||||
record_i_d: Some(test_recid),
|
||||
})),
|
||||
expect_no_header
|
||||
);
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ fn build_app<'a>() -> ArgMatches<'a> {
|
||||
--contributors 'Prints the list of contributors.'";
|
||||
App::new(&program)
|
||||
.about("Hayabusa: Aiming to be the world's greatest Windows event log analysis tool!")
|
||||
.version("1.3.0-dev")
|
||||
.version("1.3.0")
|
||||
.author("Yamato Security (https://github.com/Yamato-Security/hayabusa) @SecurityYamato")
|
||||
.setting(AppSettings::VersionlessSubcommands)
|
||||
.arg(
|
||||
|
||||
@@ -482,6 +482,11 @@ impl App {
|
||||
total_records += cnt_tmp;
|
||||
pb.inc();
|
||||
}
|
||||
if configs::CONFIG.read().unwrap().args.is_present("output") {
|
||||
println!();
|
||||
println!();
|
||||
println!("Analysis finished. Please wait while the results are being saved.");
|
||||
}
|
||||
println!();
|
||||
detection.add_aggcondition_msges(&self.rt);
|
||||
if !(*STATISTICS_FLAG || *LOGONSUMMARY_FLAG || *PIVOT_KEYWORD_LIST_FLAG) {
|
||||
|
||||
Reference in New Issue
Block a user