Hotfix/not work count#278 (#281)
* fixed countup structure #278
* fixed countup structure and count up field logic #278
* fixed tests #278
* added no output aggregation detect message when output exist in rule yaml #232
* moved get_agg_condtion to rulenode function #278
* added field_values to output count fields data #232 #278
- fixed count logic #278
- fixed count test to adjust field_values add
- added count test
* fixed count output format #232
* fixed compile error
* fixed count output #232
- moved output check to create_count_output
- fixed yaml condition reference
- adjust top and tail multi space
* added create count output test #232
* removed count by file #278
- commented by @YamatoSecurity
* changed sort function to sort_unstable_by
* fixed typo
* adjust to comment #281
ref: https://github.com/Yamato-Security/hayabusa/pull/281#discussion_r767283508
* adjust comment #281
refs
-
https://github.com/Yamato-Security/hayabusa/pull/281#discussion_r767285993
-
https://github.com/Yamato-Security/hayabusa/pull/281#discussion_r767286713
* adjust coment #281
ref:
https://github.com/Yamato-Security/hayabusa/pull/281#discussion_r767287831
* omitted code #281
* adjust comment #281
ref:
https://github.com/Yamato-Security/hayabusa/pull/281#discussion_r767302595
* adjust comment #281
ref:
https://github.com/Yamato-Security/hayabusa/pull/281#discussion_r767303168
* adjust comment
ref:
https://github.com/Yamato-Security/hayabusa/pull/281#discussion_r767307535
* omitted unnecessary code #281
* adjust comment #281
ref:
https://github.com/Yamato-Security/hayabusa/pull/281#discussion_r767288428
* adjust commnet #281
ref:
https://github.com/Yamato-Security/hayabusa/pull/281#discussion_r767286731
* adjust comment #281
ref:
https://github.com/Yamato-Security/hayabusa/pull/281#discussion_r767285716
* adjust comment #281
ref:
159191ec36 (r767288428)
* adjust test result #281
* removed debug print statement in testfunction
* adjust comment #281
ref
https://github.com/Yamato-Security/hayabusa/pull/281#discussion_r767286731
* fixed output by level #278 #284
- fixed result counting process when rule has no aggregation condition #278
- added total output by level #284
* removed unnecessary crate
* fixed output #284
* removed unnecessary total/unique sum process #284
* add testcase and fix testcase bug
* add testcase, add check to check_cout()
* fixed count logic #278
* fixed test parameter
* add testcase
* fmt
* fixed count field check process #278
* fix testcase #281
* fixed comment typo
* removed one time used variable in test case #281
* fixed count field check process #278
* changed insert position #278
* changed contributor list
* fixed contributors list`
* passed with timeframe case #278
* passed all count test #278
* removed debug print
* removed debug print
* removed debug print
* cargo fmt
* changed by0level output format #284
* reduce clone() #278 #281
* changed for loop to map #278 #281
* fixed compile error
* changed priority from output in yml to aggregation output case aggregation condition exist in rule. #232
* fixed testcase #232
* changed if-let to generics #278 #281
* fixed error when test to sample_evtx#278 #281
* changed if-let to generic #278 #281
* adjust unwrap none error #278 #281
* fixed compile error and test case failed #278
Co-authored-by: ichiichi11 <takai.wa.hajime@gmail.com>
This commit is contained in:
@@ -5,7 +5,7 @@ DustInDark(@hitenkoku): Core developer, project management, sigma count implemen
|
|||||||
Garigariganzy (@garigariganzy31): Developer, event ID statistics implementation, etc...
|
Garigariganzy (@garigariganzy31): Developer, event ID statistics implementation, etc...
|
||||||
ItiB (@itiB_S144) : Core developer, sigmac hayabusa backend, rule creation, etc...
|
ItiB (@itiB_S144) : Core developer, sigmac hayabusa backend, rule creation, etc...
|
||||||
James Takai / hachiyone(@hach1yon): Current lead developer, tokio multi-threading, sigma aggregation logic, sigmac backend, rule creation, etc…
|
James Takai / hachiyone(@hach1yon): Current lead developer, tokio multi-threading, sigma aggregation logic, sigmac backend, rule creation, etc…
|
||||||
Kazuminn (@k2warugaki): Developer
|
Kazuminn (@k47_um1n): Developer
|
||||||
Yusuke Matsui (@apt773): AD hacking working group leader, rule testing, documentation, research, support, etc...
|
Yusuke Matsui (@apt773): AD hacking working group leader, rule testing, documentation, research, support, etc...
|
||||||
Zach Mathis (@yamatosecurity, Yamato Security Founder): Project leader, tool and concept design, rule creation and tuning, etc…
|
Zach Mathis (@yamatosecurity, Yamato Security Founder): Project leader, tool and concept design, rule creation and tuning, etc…
|
||||||
|
|
||||||
@@ -14,9 +14,9 @@ Hayabusa would not have been possible without first creating RustyBlue, so we wo
|
|||||||
|
|
||||||
Zach Mathis (@yamatosecurity, Yamato Security Founder): Project Leader
|
Zach Mathis (@yamatosecurity, Yamato Security Founder): Project Leader
|
||||||
Nishikawa Akira (@nishikawaakira): Lead Developer
|
Nishikawa Akira (@nishikawaakira): Lead Developer
|
||||||
kazuminn (@k2warugaki): Core Developer
|
kazuminn (@k47_um1n): Core Developer
|
||||||
itiB (@itiB_S144): Core Developer
|
itiB (@itiB_S144): Core Developer
|
||||||
James Takai / hachiyone (@hach1yon): Developer
|
James Takai / hachiyone (@hach1yon): Core Developer
|
||||||
DustInDark (@hitenkoku): Core Developer
|
DustInDark (@hitenkoku): Core Developer
|
||||||
garigariganzy (@garigariganzy31): Developer
|
garigariganzy (@garigariganzy31): Developer
|
||||||
7itoh (@yNitocrypto22): Developer
|
7itoh (@yNitocrypto22): Developer
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ pub fn after_fact() {
|
|||||||
.ok();
|
.ok();
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut displayflag = false;
|
let mut displayflag = false;
|
||||||
let mut target: Box<dyn io::Write> =
|
let mut target: Box<dyn io::Write> =
|
||||||
if let Some(csv_path) = configs::CONFIG.read().unwrap().args.value_of("output") {
|
if let Some(csv_path) = configs::CONFIG.read().unwrap().args.value_of("output") {
|
||||||
@@ -77,8 +78,13 @@ fn emit_csv<W: std::io::Write>(writer: &mut W, displayflag: bool) -> io::Result<
|
|||||||
} else {
|
} else {
|
||||||
wtr = csv::WriterBuilder::new().from_writer(writer);
|
wtr = csv::WriterBuilder::new().from_writer(writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
let messages = print::MESSAGES.lock().unwrap();
|
let messages = print::MESSAGES.lock().unwrap();
|
||||||
let mut detect_count = 0;
|
// levelの区分が"Critical","High","Medium","Low","Informational","Undefined"の6つであるため
|
||||||
|
let mut total_detect_counts_by_level: Vec<u128> = vec![0; 6];
|
||||||
|
let mut unique_detect_counts_by_level: Vec<u128> = vec![0; 6];
|
||||||
|
let mut detected_rule_files: Vec<String> = Vec::new();
|
||||||
|
|
||||||
for (time, detect_infos) in messages.iter() {
|
for (time, detect_infos) in messages.iter() {
|
||||||
for detect_info in detect_infos {
|
for detect_info in detect_infos {
|
||||||
if displayflag {
|
if displayflag {
|
||||||
@@ -103,17 +109,61 @@ fn emit_csv<W: std::io::Write>(writer: &mut W, displayflag: bool) -> io::Result<
|
|||||||
details: &detect_info.detail,
|
details: &detect_info.detail,
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
let level_suffix = *configs::LEVELMAP
|
||||||
|
.get(&detect_info.level.to_uppercase())
|
||||||
|
.unwrap_or(&0) as usize;
|
||||||
|
if !detected_rule_files.contains(&detect_info.rulepath) {
|
||||||
|
detected_rule_files.push(detect_info.rulepath.clone());
|
||||||
|
unique_detect_counts_by_level[level_suffix] += 1;
|
||||||
|
}
|
||||||
|
total_detect_counts_by_level[level_suffix] += 1;
|
||||||
}
|
}
|
||||||
detect_count += detect_infos.len();
|
|
||||||
}
|
}
|
||||||
println!("");
|
println!("");
|
||||||
|
|
||||||
wtr.flush()?;
|
wtr.flush()?;
|
||||||
println!("");
|
println!("");
|
||||||
println!("Total events: {:?}", detect_count);
|
_print_unique_results(
|
||||||
|
total_detect_counts_by_level,
|
||||||
|
"Total".to_string(),
|
||||||
|
"detections".to_string(),
|
||||||
|
);
|
||||||
|
_print_unique_results(
|
||||||
|
unique_detect_counts_by_level,
|
||||||
|
"Unique".to_string(),
|
||||||
|
"rules".to_string(),
|
||||||
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 与えられたユニークな検知数と全体の検知数の情報(レベル別と総計)を元に結果文を標準出力に表示する関数
|
||||||
|
fn _print_unique_results(mut counts_by_level: Vec<u128>, head_word: String, tail_word: String) {
|
||||||
|
let levels = Vec::from([
|
||||||
|
"Critical",
|
||||||
|
"High",
|
||||||
|
"Medium",
|
||||||
|
"Low",
|
||||||
|
"Informational",
|
||||||
|
"Undefined",
|
||||||
|
]);
|
||||||
|
|
||||||
|
// configsの登録順番と表示をさせたいlevelの順番が逆であるため
|
||||||
|
counts_by_level.reverse();
|
||||||
|
|
||||||
|
// 全体の集計(levelの記載がないためformatの第二引数は空の文字列)
|
||||||
|
println!(
|
||||||
|
"{} {}:{}",
|
||||||
|
head_word,
|
||||||
|
tail_word,
|
||||||
|
counts_by_level.iter().sum::<u128>()
|
||||||
|
);
|
||||||
|
for (i, level_name) in levels.iter().enumerate() {
|
||||||
|
println!(
|
||||||
|
"{} {} {}:{}",
|
||||||
|
head_word, level_name, tail_word, counts_by_level[i]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
fn format_time(time: &DateTime<Utc>) -> String {
|
fn format_time(time: &DateTime<Utc>) -> String {
|
||||||
if configs::CONFIG.read().unwrap().args.is_present("utc") {
|
if configs::CONFIG.read().unwrap().args.is_present("utc") {
|
||||||
format_rfc(time)
|
format_rfc(time)
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
extern crate csv;
|
extern crate csv;
|
||||||
|
|
||||||
use crate::detections::configs;
|
|
||||||
use crate::detections::print::AlertMessage;
|
use crate::detections::print::AlertMessage;
|
||||||
use crate::detections::print::MESSAGES;
|
use crate::detections::print::MESSAGES;
|
||||||
use crate::detections::rule;
|
use crate::detections::rule;
|
||||||
@@ -132,7 +131,7 @@ impl Detection {
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_aggcondtion_msg(&self) {
|
pub fn add_aggcondition_msg(&self) {
|
||||||
for rule in &self.rules {
|
for rule in &self.rules {
|
||||||
if !rule.has_agg_condition() {
|
if !rule.has_agg_condition() {
|
||||||
continue;
|
continue;
|
||||||
@@ -145,46 +144,11 @@ impl Detection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print_unique_results(&self) {
|
|
||||||
let rules = &self.rules;
|
|
||||||
let levellabel = Vec::from([
|
|
||||||
"Critical",
|
|
||||||
"High",
|
|
||||||
"Medium",
|
|
||||||
"Low",
|
|
||||||
"Informational",
|
|
||||||
"Undefined",
|
|
||||||
]);
|
|
||||||
// levclcounts is [(Undefined), (Informational), (Low),(Medium),(High),(Critical)]
|
|
||||||
let mut levelcounts = Vec::from([0, 0, 0, 0, 0, 0]);
|
|
||||||
for rule in rules.into_iter() {
|
|
||||||
if rule.check_exist_countdata() {
|
|
||||||
let suffix = configs::LEVELMAP
|
|
||||||
.get(
|
|
||||||
&rule.yaml["level"]
|
|
||||||
.as_str()
|
|
||||||
.unwrap_or("")
|
|
||||||
.to_owned()
|
|
||||||
.to_uppercase(),
|
|
||||||
)
|
|
||||||
.unwrap_or(&0);
|
|
||||||
levelcounts[*suffix as usize] += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let mut total_unique = 0;
|
|
||||||
levelcounts.reverse();
|
|
||||||
for (i, value) in levelcounts.iter().enumerate() {
|
|
||||||
println!("{} alerts: {}", levellabel[i], value);
|
|
||||||
total_unique += value;
|
|
||||||
}
|
|
||||||
println!("Unique alerts detected: {}", total_unique);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 複数のイベントレコードに対して、ルールを1個実行します。
|
// 複数のイベントレコードに対して、ルールを1個実行します。
|
||||||
fn execute_rule(mut rule: RuleNode, records: Arc<Vec<EvtxRecordInfo>>) -> RuleNode {
|
fn execute_rule(mut rule: RuleNode, records: Arc<Vec<EvtxRecordInfo>>) -> RuleNode {
|
||||||
let agg_condition = rule.has_agg_condition();
|
let agg_condition = rule.has_agg_condition();
|
||||||
for record_info in records.as_ref() {
|
for record_info in records.as_ref() {
|
||||||
let result = rule.select(&record_info.evtx_filepath, &record_info);
|
let result = rule.select(&record_info);
|
||||||
if !result {
|
if !result {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -219,34 +183,63 @@ impl Detection {
|
|||||||
fn insert_agg_message(rule: &RuleNode, agg_result: AggResult) {
|
fn insert_agg_message(rule: &RuleNode, agg_result: AggResult) {
|
||||||
let output = Detection::create_count_output(rule, &agg_result);
|
let output = Detection::create_count_output(rule, &agg_result);
|
||||||
MESSAGES.lock().unwrap().insert_message(
|
MESSAGES.lock().unwrap().insert_message(
|
||||||
agg_result.filepath,
|
"-".to_owned(),
|
||||||
rule.rulepath.to_string(),
|
rule.rulepath.to_owned(),
|
||||||
agg_result.start_timedate,
|
agg_result.start_timedate,
|
||||||
rule.yaml["level"].as_str().unwrap_or("").to_string(),
|
rule.yaml["level"].as_str().unwrap_or("").to_owned(),
|
||||||
"-".to_string(),
|
"-".to_owned(),
|
||||||
"-".to_string(),
|
"-".to_owned(),
|
||||||
rule.yaml["title"].as_str().unwrap_or("").to_string(),
|
rule.yaml["title"].as_str().unwrap_or("").to_owned(),
|
||||||
output.to_string(),
|
output.to_owned(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
///aggregation conditionのcount部分の検知出力文の文字列を返す関数
|
///aggregation conditionのcount部分の検知出力文の文字列を返す関数
|
||||||
fn create_count_output(rule: &RuleNode, agg_result: &AggResult) -> String {
|
fn create_count_output(rule: &RuleNode, agg_result: &AggResult) -> String {
|
||||||
let mut ret: String = "count(".to_owned();
|
// 条件式部分の出力
|
||||||
let key: Vec<&str> = agg_result.key.split("_").collect();
|
let mut ret: String = "[condition] ".to_owned();
|
||||||
if key.len() >= 1 {
|
let agg_condition_raw_str: Vec<&str> = rule.yaml["detection"]["condition"]
|
||||||
ret.push_str(key[0]);
|
.as_str()
|
||||||
}
|
.unwrap()
|
||||||
ret.push_str(&") ");
|
.split("|")
|
||||||
if key.len() >= 2 {
|
.collect();
|
||||||
ret.push_str("by ");
|
// この関数が呼び出されている段階で既にaggregation conditionは存在する前提なのでunwrap前の確認は行わない
|
||||||
ret.push_str(key[1]);
|
let agg_condition = rule.get_agg_condition().unwrap();
|
||||||
|
let exist_timeframe = rule.yaml["detection"]["timeframe"]
|
||||||
|
.as_str()
|
||||||
|
.unwrap_or("")
|
||||||
|
.to_string()
|
||||||
|
!= "";
|
||||||
|
// この関数が呼び出されている段階で既にaggregation conditionは存在する前提なのでagg_conditionの配列の長さは2となる
|
||||||
|
ret.push_str(agg_condition_raw_str[1].trim());
|
||||||
|
if exist_timeframe {
|
||||||
|
ret.push_str(" in timeframe");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret.push_str(&format!(" [result] count:{}", agg_result.data));
|
||||||
|
if agg_condition._field_name.is_some() {
|
||||||
ret.push_str(&format!(
|
ret.push_str(&format!(
|
||||||
"{} in {}.",
|
" {}:{}",
|
||||||
agg_result.condition_op_num,
|
agg_condition._field_name.as_ref().unwrap(),
|
||||||
rule.yaml["timeframe"].as_str().unwrap_or(""),
|
agg_result.field_values.join("/")
|
||||||
));
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if agg_condition._by_field_name.is_some() {
|
||||||
|
ret.push_str(&format!(
|
||||||
|
" {}:{}",
|
||||||
|
agg_condition._by_field_name.as_ref().unwrap(),
|
||||||
|
agg_result.key
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if exist_timeframe {
|
||||||
|
ret.push_str(&format!(
|
||||||
|
" timeframe:{}",
|
||||||
|
rule.yaml["detection"]["timeframe"].as_str().unwrap()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
pub fn print_rule_load_info(
|
pub fn print_rule_load_info(
|
||||||
@@ -266,10 +259,196 @@ impl Detection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[cfg(test)]
|
||||||
fn test_parse_rule_files() {
|
mod tests {
|
||||||
|
|
||||||
|
use crate::detections::detection::Detection;
|
||||||
|
use crate::detections::rule::create_rule;
|
||||||
|
use crate::detections::rule::AggResult;
|
||||||
|
use crate::filter;
|
||||||
|
use chrono::{TimeZone, Utc};
|
||||||
|
use yaml_rust::YamlLoader;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_rule_files() {
|
||||||
let level = "informational";
|
let level = "informational";
|
||||||
let opt_rule_path = Some("./test_files/rules/level_yaml");
|
let opt_rule_path = Some("./test_files/rules/level_yaml");
|
||||||
let cole = Detection::parse_rule_files(level.to_owned(), opt_rule_path, &filter::exclude_ids());
|
let cole =
|
||||||
|
Detection::parse_rule_files(level.to_owned(), opt_rule_path, &filter::exclude_ids());
|
||||||
assert_eq!(5, cole.len());
|
assert_eq!(5, cole.len());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_output_aggregation_output_with_output() {
|
||||||
|
let default_time = Utc.ymd(1977, 1, 1).and_hms(0, 0, 0);
|
||||||
|
let agg_result: AggResult =
|
||||||
|
AggResult::new(2, "_".to_string(), vec![], default_time, ">= 1".to_string());
|
||||||
|
let rule_str = r#"
|
||||||
|
enabled: true
|
||||||
|
detection:
|
||||||
|
selection1:
|
||||||
|
Channel: 'System'
|
||||||
|
selection2:
|
||||||
|
EventID: 7040
|
||||||
|
selection3:
|
||||||
|
param1: 'Windows Event Log'
|
||||||
|
condition: selection1 and selection2 and selection3 | count() >= 1
|
||||||
|
output: testdata
|
||||||
|
"#;
|
||||||
|
let mut rule_yaml = YamlLoader::load_from_str(rule_str).unwrap().into_iter();
|
||||||
|
let test = rule_yaml.next().unwrap();
|
||||||
|
let mut rule_node = create_rule("testpath".to_string(), test);
|
||||||
|
rule_node.init().ok();
|
||||||
|
let expected_output = "[condition] count() >= 1 [result] count:2";
|
||||||
|
assert_eq!(
|
||||||
|
Detection::create_count_output(&rule_node, &agg_result),
|
||||||
|
expected_output
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_output_aggregation_output_no_filed_by() {
|
||||||
|
let default_time = Utc.ymd(1977, 1, 1).and_hms(0, 0, 0);
|
||||||
|
let agg_result: AggResult =
|
||||||
|
AggResult::new(2, "_".to_string(), vec![], default_time, ">= 1".to_string());
|
||||||
|
let rule_str = r#"
|
||||||
|
enabled: true
|
||||||
|
detection:
|
||||||
|
selection1:
|
||||||
|
Channel: 'System'
|
||||||
|
selection2:
|
||||||
|
EventID: 7040
|
||||||
|
selection3:
|
||||||
|
param1: 'Windows Event Log'
|
||||||
|
condition: selection1 and selection2 and selection3 | count() >= 1
|
||||||
|
"#;
|
||||||
|
let mut rule_yaml = YamlLoader::load_from_str(rule_str).unwrap().into_iter();
|
||||||
|
let test = rule_yaml.next().unwrap();
|
||||||
|
let mut rule_node = create_rule("testpath".to_string(), test);
|
||||||
|
rule_node.init().ok();
|
||||||
|
let expected_output = "[condition] count() >= 1 [result] count:2";
|
||||||
|
assert_eq!(
|
||||||
|
Detection::create_count_output(&rule_node, &agg_result),
|
||||||
|
expected_output
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_output_aggregation_output_with_timeframe() {
|
||||||
|
let default_time = Utc.ymd(1977, 1, 1).and_hms(0, 0, 0);
|
||||||
|
let agg_result: AggResult =
|
||||||
|
AggResult::new(2, "_".to_string(), vec![], default_time, ">= 1".to_string());
|
||||||
|
let rule_str = r#"
|
||||||
|
enabled: true
|
||||||
|
detection:
|
||||||
|
selection1:
|
||||||
|
Channel: 'System'
|
||||||
|
selection2:
|
||||||
|
EventID: 7040
|
||||||
|
selection3:
|
||||||
|
param1: 'Windows Event Log'
|
||||||
|
condition: selection1 and selection2 and selection3 | count() >= 1
|
||||||
|
timeframe: 15m
|
||||||
|
"#;
|
||||||
|
let mut rule_yaml = YamlLoader::load_from_str(rule_str).unwrap().into_iter();
|
||||||
|
let test = rule_yaml.next().unwrap();
|
||||||
|
let mut rule_node = create_rule("testpath".to_string(), test);
|
||||||
|
rule_node.init().ok();
|
||||||
|
let expected_output =
|
||||||
|
"[condition] count() >= 1 in timeframe [result] count:2 timeframe:15m";
|
||||||
|
assert_eq!(
|
||||||
|
Detection::create_count_output(&rule_node, &agg_result),
|
||||||
|
expected_output
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_output_aggregation_output_with_field() {
|
||||||
|
let default_time = Utc.ymd(1977, 1, 1).and_hms(0, 0, 0);
|
||||||
|
let agg_result: AggResult = AggResult::new(
|
||||||
|
2,
|
||||||
|
"_".to_string(),
|
||||||
|
vec!["7040".to_owned(), "9999".to_owned()],
|
||||||
|
default_time,
|
||||||
|
">= 1".to_string(),
|
||||||
|
);
|
||||||
|
let rule_str = r#"
|
||||||
|
enabled: true
|
||||||
|
detection:
|
||||||
|
selection1:
|
||||||
|
Channel: 'System'
|
||||||
|
selection2:
|
||||||
|
param1: 'Windows Event Log'
|
||||||
|
condition: selection1 and selection2 | count(EventID) >= 1
|
||||||
|
"#;
|
||||||
|
let mut rule_yaml = YamlLoader::load_from_str(rule_str).unwrap().into_iter();
|
||||||
|
let test = rule_yaml.next().unwrap();
|
||||||
|
let mut rule_node = create_rule("testpath".to_string(), test);
|
||||||
|
rule_node.init().ok();
|
||||||
|
let expected_output = "[condition] count(EventID) >= 1 [result] count:2 EventID:7040/9999";
|
||||||
|
assert_eq!(
|
||||||
|
Detection::create_count_output(&rule_node, &agg_result),
|
||||||
|
expected_output
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_output_aggregation_output_with_field_by() {
|
||||||
|
let default_time = Utc.ymd(1977, 1, 1).and_hms(0, 0, 0);
|
||||||
|
let agg_result: AggResult = AggResult::new(
|
||||||
|
2,
|
||||||
|
"lsass.exe".to_string(),
|
||||||
|
vec!["0000".to_owned(), "1111".to_owned()],
|
||||||
|
default_time,
|
||||||
|
">= 1".to_string(),
|
||||||
|
);
|
||||||
|
let rule_str = r#"
|
||||||
|
enabled: true
|
||||||
|
detection:
|
||||||
|
selection1:
|
||||||
|
Channel: 'System'
|
||||||
|
selection2:
|
||||||
|
param1: 'Windows Event Log'
|
||||||
|
condition: selection1 and selection2 | count(EventID) by process >= 1
|
||||||
|
"#;
|
||||||
|
let mut rule_yaml = YamlLoader::load_from_str(rule_str).unwrap().into_iter();
|
||||||
|
let test = rule_yaml.next().unwrap();
|
||||||
|
let mut rule_node = create_rule("testpath".to_string(), test);
|
||||||
|
rule_node.init().ok();
|
||||||
|
let expected_output = "[condition] count(EventID) by process >= 1 [result] count:2 EventID:0000/1111 process:lsass.exe";
|
||||||
|
assert_eq!(
|
||||||
|
Detection::create_count_output(&rule_node, &agg_result),
|
||||||
|
expected_output
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_output_aggregation_output_with_by() {
|
||||||
|
let default_time = Utc.ymd(1977, 1, 1).and_hms(0, 0, 0);
|
||||||
|
let agg_result: AggResult = AggResult::new(
|
||||||
|
2,
|
||||||
|
"lsass.exe".to_string(),
|
||||||
|
vec![],
|
||||||
|
default_time,
|
||||||
|
">= 1".to_string(),
|
||||||
|
);
|
||||||
|
let rule_str = r#"
|
||||||
|
enabled: true
|
||||||
|
detection:
|
||||||
|
selection1:
|
||||||
|
Channel: 'System'
|
||||||
|
selection2:
|
||||||
|
param1: 'Windows Event Log'
|
||||||
|
condition: selection1 and selection2 | count() by process >= 1
|
||||||
|
"#;
|
||||||
|
let mut rule_yaml = YamlLoader::load_from_str(rule_str).unwrap().into_iter();
|
||||||
|
let test = rule_yaml.next().unwrap();
|
||||||
|
let mut rule_node = create_rule("testpath".to_string(), test);
|
||||||
|
rule_node.init().ok();
|
||||||
|
let expected_output =
|
||||||
|
"[condition] count() by process >= 1 [result] count:2 process:lsass.exe";
|
||||||
|
assert_eq!(
|
||||||
|
Detection::create_count_output(&rule_node, &agg_result),
|
||||||
|
expected_output
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -538,10 +538,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(
|
assert_eq!(rule_node.select(&recinfo), expect_select);
|
||||||
rule_node.select(&"testpath".to_owned(), &recinfo),
|
|
||||||
expect_select
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Err(_rec) => {
|
Err(_rec) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -584,7 +581,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_rec) => {
|
Err(_rec) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -628,7 +625,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_rec) => {
|
Err(_rec) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -707,7 +707,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "failed to parse json record.");
|
||||||
@@ -737,7 +737,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -767,7 +767,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "failed to parse json record.");
|
||||||
@@ -798,7 +798,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -829,7 +829,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -859,7 +859,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -889,7 +889,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -920,7 +920,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -951,7 +951,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -982,7 +982,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -1013,7 +1013,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -1044,7 +1044,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -1074,7 +1074,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -1108,7 +1108,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -1142,7 +1142,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -1175,7 +1175,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -1217,7 +1217,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_rec) => {
|
Err(_rec) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -1259,7 +1259,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_rec) => {
|
Err(_rec) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -1301,7 +1301,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_rec) => {
|
Err(_rec) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -1343,7 +1343,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_rec) => {
|
Err(_rec) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -1385,7 +1385,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_rec) => {
|
Err(_rec) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -1427,7 +1427,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_rec) => {
|
Err(_rec) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -1457,7 +1457,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -1487,7 +1487,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -1517,7 +1517,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -1605,7 +1605,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -1635,7 +1635,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -1667,7 +1667,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -1699,7 +1699,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ use self::aggregation_parser::AggregationParseInfo;
|
|||||||
|
|
||||||
mod condition_parser;
|
mod condition_parser;
|
||||||
mod count;
|
mod count;
|
||||||
use self::count::TimeFrameInfo;
|
use self::count::{AggRecordTimeInfo, TimeFrameInfo};
|
||||||
|
|
||||||
use super::detection::EvtxRecordInfo;
|
use super::detection::EvtxRecordInfo;
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ pub struct RuleNode {
|
|||||||
pub rulepath: String,
|
pub rulepath: String,
|
||||||
pub yaml: Yaml,
|
pub yaml: Yaml,
|
||||||
detection: DetectionNode,
|
detection: DetectionNode,
|
||||||
countdata: HashMap<String, HashMap<String, Vec<DateTime<Utc>>>>,
|
countdata: HashMap<String, Vec<AggRecordTimeInfo>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for RuleNode {
|
impl Debug for RuleNode {
|
||||||
@@ -66,10 +66,10 @@ impl RuleNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select(&mut self, filepath: &String, event_record: &EvtxRecordInfo) -> bool {
|
pub fn select(&mut self, event_record: &EvtxRecordInfo) -> bool {
|
||||||
let result = self.detection.select(event_record);
|
let result = self.detection.select(event_record);
|
||||||
if result {
|
if result && self.has_agg_condition() {
|
||||||
count::count(self, filepath, &event_record.record);
|
count::count(self, &event_record.record);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -83,14 +83,23 @@ impl RuleNode {
|
|||||||
if !self.has_agg_condition() {
|
if !self.has_agg_condition() {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
for filepath in self.countdata.keys() {
|
ret.append(&mut count::aggregation_condition_select(&self));
|
||||||
ret.append(&mut count::aggregation_condition_select(&self, &filepath));
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
pub fn check_exist_countdata(&self) -> bool {
|
pub fn check_exist_countdata(&self) -> bool {
|
||||||
self.countdata.len() > 0
|
self.countdata.len() > 0
|
||||||
}
|
}
|
||||||
|
/// ルール内のAggregationParseInfo(Aggregation Condition)を取得する関数
|
||||||
|
pub fn get_agg_condition(&self) -> Option<&AggregationParseInfo> {
|
||||||
|
match self.detection.aggregation_condition.as_ref() {
|
||||||
|
None => {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(agg_parse_info) => {
|
||||||
|
return Some(agg_parse_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RuleNodeのdetectionに定義されているキーの一覧を取得する。
|
// RuleNodeのdetectionに定義されているキーの一覧を取得する。
|
||||||
@@ -293,12 +302,12 @@ impl DetectionNode {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
/// countなどのaggregationの結果を出力する構造体
|
/// countなどのaggregationの結果を出力する構造体
|
||||||
pub struct AggResult {
|
pub struct AggResult {
|
||||||
/// evtx file path
|
|
||||||
pub filepath: String,
|
|
||||||
/// countなどの値
|
/// countなどの値
|
||||||
pub data: i32,
|
pub data: i32,
|
||||||
/// (countの括弧内の記載)_(count byで指定された条件)で設定されたキー
|
/// count byで指定された条件のレコード内での値
|
||||||
pub key: String,
|
pub key: String,
|
||||||
|
/// countの括弧内指定された項目の検知されたレコード内での値の配列。括弧内で指定がなかった場合は長さ0の配列となる
|
||||||
|
pub field_values: Vec<String>,
|
||||||
///検知したブロックの最初のレコードの時間
|
///検知したブロックの最初のレコードの時間
|
||||||
pub start_timedate: DateTime<Utc>,
|
pub start_timedate: DateTime<Utc>,
|
||||||
///条件式の情報
|
///条件式の情報
|
||||||
@@ -307,16 +316,16 @@ pub struct AggResult {
|
|||||||
|
|
||||||
impl AggResult {
|
impl AggResult {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
filepath: String,
|
|
||||||
data: i32,
|
data: i32,
|
||||||
key: String,
|
key: String,
|
||||||
|
field_values: Vec<String>,
|
||||||
start_timedate: DateTime<Utc>,
|
start_timedate: DateTime<Utc>,
|
||||||
condition_op_num: String,
|
condition_op_num: String,
|
||||||
) -> AggResult {
|
) -> AggResult {
|
||||||
return AggResult {
|
return AggResult {
|
||||||
filepath: filepath,
|
|
||||||
data: data,
|
data: data,
|
||||||
key: key,
|
key: key,
|
||||||
|
field_values: field_values,
|
||||||
start_timedate: start_timedate,
|
start_timedate: start_timedate,
|
||||||
condition_op_num: condition_op_num,
|
condition_op_num: condition_op_num,
|
||||||
};
|
};
|
||||||
@@ -361,7 +370,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -391,7 +400,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -421,7 +430,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -504,7 +513,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -563,7 +572,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -629,7 +638,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -673,7 +682,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -718,7 +727,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -782,7 +791,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -846,7 +855,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -892,7 +901,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_rec) => {
|
Err(_rec) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -950,17 +959,11 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
let result = rule_node.select(&"testpath".to_string(), &recinfo);
|
let result = rule_node.select(&recinfo);
|
||||||
assert_eq!(rule_node.detection.aggregation_condition.is_some(), true);
|
assert_eq!(rule_node.detection.aggregation_condition.is_some(), true);
|
||||||
assert_eq!(result, true);
|
assert_eq!(result, true);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
*&rule_node
|
*&rule_node.countdata.get(key).unwrap().len() as i32,
|
||||||
.countdata
|
|
||||||
.get("testpath")
|
|
||||||
.unwrap()
|
|
||||||
.get(key)
|
|
||||||
.unwrap()
|
|
||||||
.len() as i32,
|
|
||||||
expect_count
|
expect_count
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -432,7 +432,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -465,7 +465,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -497,7 +497,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -529,7 +529,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
@@ -561,7 +561,7 @@ mod tests {
|
|||||||
Ok(record) => {
|
Ok(record) => {
|
||||||
let keys = detections::rule::get_detection_keys(&rule_node);
|
let keys = detections::rule::get_detection_keys(&rule_node);
|
||||||
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
let recinfo = utils::create_rec_info(record, "testpath".to_owned(), &keys);
|
||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "Failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
|
|||||||
@@ -171,7 +171,6 @@ impl App {
|
|||||||
pb.inc();
|
pb.inc();
|
||||||
}
|
}
|
||||||
after_fact();
|
after_fact();
|
||||||
detection.print_unique_results();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Windowsイベントログファイルを1ファイル分解析する。
|
// Windowsイベントログファイルを1ファイル分解析する。
|
||||||
@@ -237,7 +236,7 @@ impl App {
|
|||||||
detection = detection.start(&self.rt, records_per_detect);
|
detection = detection.start(&self.rt, records_per_detect);
|
||||||
}
|
}
|
||||||
|
|
||||||
detection.add_aggcondtion_msg();
|
detection.add_aggcondition_msg();
|
||||||
tl.tm_stats_dsp_msg();
|
tl.tm_stats_dsp_msg();
|
||||||
|
|
||||||
return detection;
|
return detection;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ pub struct Timeline {
|
|||||||
impl Timeline {
|
impl Timeline {
|
||||||
pub fn new() -> Timeline {
|
pub fn new() -> Timeline {
|
||||||
let totalcnt = 0;
|
let totalcnt = 0;
|
||||||
let filepath = "".to_owned();
|
let filepath = String::default();
|
||||||
let starttm = "".to_string();
|
let starttm = "".to_string();
|
||||||
let endtm = "".to_string();
|
let endtm = "".to_string();
|
||||||
let statslst = HashMap::new();
|
let statslst = HashMap::new();
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
let _ = &yaml.read_dir(
|
let _ = &yaml.read_dir(
|
||||||
"test_files/rules/yaml/".to_string(),
|
"test_files/rules/yaml/".to_string(),
|
||||||
&"".to_owned(),
|
&String::default(),
|
||||||
&exclude_ids,
|
&exclude_ids,
|
||||||
);
|
);
|
||||||
assert_ne!(yaml.files.len(), 0);
|
assert_ne!(yaml.files.len(), 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user