feat: emit DateTime with selected timezone
@fox
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
use crate::detections::configs;
|
use crate::detections::configs;
|
||||||
use crate::detections::print;
|
use crate::detections::print;
|
||||||
use chrono::{DateTime, TimeZone, Utc};
|
use chrono::Local;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
@@ -10,7 +10,7 @@ use std::process;
|
|||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
#[serde(rename_all = "PascalCase")]
|
#[serde(rename_all = "PascalCase")]
|
||||||
pub struct CsvFormat<'a> {
|
pub struct CsvFormat<'a> {
|
||||||
time: DateTime<Utc>,
|
time: &'a str,
|
||||||
message: &'a str,
|
message: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,9 +39,24 @@ fn emit_csv(writer: &mut Box<dyn io::Write>) -> Result<(), Box<dyn Error>> {
|
|||||||
let messages = print::MESSAGES.lock().unwrap();
|
let messages = print::MESSAGES.lock().unwrap();
|
||||||
|
|
||||||
for (time, texts) in messages.iter() {
|
for (time, texts) in messages.iter() {
|
||||||
|
let formated_time = if configs::singleton().args.is_present("utc") {
|
||||||
|
if configs::singleton().args.is_present("rfc-2822") {
|
||||||
|
time.to_rfc2822()
|
||||||
|
} else {
|
||||||
|
time.to_rfc3339()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let time_local = time.with_timezone(&Local);
|
||||||
|
if configs::singleton().args.is_present("rfc-2822") {
|
||||||
|
time_local.to_rfc2822()
|
||||||
|
} else {
|
||||||
|
time_local.to_rfc3339()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
for text in texts {
|
for text in texts {
|
||||||
wtr.serialize(CsvFormat {
|
wtr.serialize(CsvFormat {
|
||||||
time: *time,
|
time: &formated_time,
|
||||||
message: text,
|
message: text,
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
@@ -78,8 +93,7 @@ fn test_emit_csv() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let expect = "Time,Message
|
let expect = "Time,Message
|
||||||
1996-02-27T01:05:01Z,pokepoke
|
1996-02-2";
|
||||||
";
|
|
||||||
|
|
||||||
let mut file: Box<dyn io::Write> =
|
let mut file: Box<dyn io::Write> =
|
||||||
Box::new(File::create("./test_emit_csv.csv".to_string()).unwrap());
|
Box::new(File::create("./test_emit_csv.csv".to_string()).unwrap());
|
||||||
@@ -87,7 +101,9 @@ fn test_emit_csv() {
|
|||||||
|
|
||||||
match read_to_string("./test_emit_csv.csv") {
|
match read_to_string("./test_emit_csv.csv") {
|
||||||
Err(_) => panic!("Failed to open file"),
|
Err(_) => panic!("Failed to open file"),
|
||||||
Ok(s) => assert_eq!(s, expect),
|
Ok(s) => {
|
||||||
|
assert_eq!(&s[0..22], expect);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
assert!(remove_file("./test_emit_csv.csv").is_ok());
|
assert!(remove_file("./test_emit_csv.csv").is_ok());
|
||||||
|
|||||||
@@ -45,11 +45,11 @@ fn build_app() -> clap::App<'static, 'static> {
|
|||||||
.arg(Arg::from_usage("--attackhunt=[ATTACK_HUNT] 'Attack Hunt'"))
|
.arg(Arg::from_usage("--attackhunt=[ATTACK_HUNT] 'Attack Hunt'"))
|
||||||
.arg(Arg::from_usage("--csv-timeline=[CSV_TIMELINE] 'csv output timeline'"))
|
.arg(Arg::from_usage("--csv-timeline=[CSV_TIMELINE] 'csv output timeline'"))
|
||||||
.arg(Arg::from_usage("--human-readable-timeline=[HUMAN_READABLE_TIMELINE] 'human readable timeline'"))
|
.arg(Arg::from_usage("--human-readable-timeline=[HUMAN_READABLE_TIMELINE] 'human readable timeline'"))
|
||||||
|
.arg(Arg::from_usage("--rfc-2822 'output date and time in RFC 2822 format. Example: Mon, 07 Aug 2006 12:34:56 -0600'"))
|
||||||
.arg(Arg::from_usage("-l --lang=[LANG] 'output language'"))
|
.arg(Arg::from_usage("-l --lang=[LANG] 'output language'"))
|
||||||
.arg(Arg::from_usage("-t --timezone=[TIMEZONE] 'timezone setting'"))
|
.arg(Arg::from_usage("-u --utc 'output time in UTC format(default: local time)'"))
|
||||||
.arg(Arg::from_usage("-d --directory 'event log files directory'"))
|
.arg(Arg::from_usage("-d --directory 'event log files directory'"))
|
||||||
.arg(Arg::from_usage("-s --statistics 'event statistics'"))
|
.arg(Arg::from_usage("-s --statistics 'event statistics'"))
|
||||||
.arg(Arg::from_usage("-u --update 'signature update'"))
|
|
||||||
.arg(Arg::from_usage("--credits 'Zachary Mathis, Akira Nishikawa'"))
|
.arg(Arg::from_usage("--credits 'Zachary Mathis, Akira Nishikawa'"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use crate::detections::rule;
|
|||||||
use crate::detections::rule::RuleNode;
|
use crate::detections::rule::RuleNode;
|
||||||
use crate::yaml::ParseYaml;
|
use crate::yaml::ParseYaml;
|
||||||
|
|
||||||
use chrono::{DateTime, FixedOffset, TimeZone, Utc};
|
|
||||||
use evtx::EvtxParser;
|
use evtx::EvtxParser;
|
||||||
use serde_json::{Error, Value};
|
use serde_json::{Error, Value};
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
extern crate serde;
|
extern crate serde;
|
||||||
#[macro_use]
|
|
||||||
extern crate serde_derive;
|
|
||||||
|
|
||||||
use evtx::EvtxParser;
|
use evtx::EvtxParser;
|
||||||
use quick_xml::de::DeError;
|
use quick_xml::de::DeError;
|
||||||
|
|||||||
Reference in New Issue
Block a user