英語修正 (#236)
* 英語修正 * cargo fmt * fixed test assertion string data Co-authored-by: DustInDark <nextsasasa@gmail.com>
This commit is contained in:
@@ -106,7 +106,7 @@ fn emit_csv<W: std::io::Write>(writer: &mut W, displayflag: bool) -> io::Result<
|
|||||||
|
|
||||||
wtr.flush()?;
|
wtr.flush()?;
|
||||||
println!("");
|
println!("");
|
||||||
println!("Total Events Detected:{:?}", detect_count);
|
println!("Total events detected: {:?}", detect_count);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,7 +202,7 @@ fn test_emit_csv() {
|
|||||||
assert!(emit_csv(&mut file, false).is_ok());
|
assert!(emit_csv(&mut file, false).is_ok());
|
||||||
|
|
||||||
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) => {
|
Ok(s) => {
|
||||||
assert_eq!(s, expect);
|
assert_eq!(s, expect);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,23 +47,23 @@ fn build_app<'a>() -> ArgMatches<'a> {
|
|||||||
return ArgMatches::default();
|
return ArgMatches::default();
|
||||||
}
|
}
|
||||||
|
|
||||||
let usages = "-f --filepath=[FILEPATH] 'Event file path'
|
let usages = "-f --filepath=[FILEPATH] 'File path to one .evtx file'
|
||||||
--csv-timeline=[CSV_TIMELINE] 'Csv output timeline'
|
--csv-timeline=[CSV_TIMELINE] 'Save the timeline in CSV format'
|
||||||
--rfc-2822 'Output date and time in RFC 2822 format. Example: Mon, 07 Aug 2006 12:34:56 -0600'
|
--rfc-2822 'Output date and time in RFC 2822 format. Example: Mon, 07 Aug 2006 12:34:56 -0600'
|
||||||
--rfc-3339 'Output date and time in RFC 3339 format. Example: 2006-08-07T12:34:56.485214 -06:00'
|
--rfc-3339 'Output date and time in RFC 3339 format. Example: 2006-08-07T12:34:56.485214 -06:00'
|
||||||
--verbose 'Output check information to target event file path and rule file.'
|
--verbose 'Output verbose information to target event file path and rule file'
|
||||||
-q 'Quiet Output Logo'
|
-q 'Quiet mode. Do not display the launch banner'
|
||||||
-r --rules=[RULEDIRECTORY] 'using target of rule file directory'
|
-r --rules=[RULEDIRECTORY] 'Rule file directory (default: ./rules)'
|
||||||
-L --level=[LEVEL] 'Specified execute rule level(default: LOW)'
|
-L --level=[LEVEL] 'Minimum level for rules (default: low)'
|
||||||
-u --utc 'Output time in UTC format(default: local time)'
|
-u --utc 'Output time in UTC format (default: local time)'
|
||||||
-d --directory=[DIRECTORY] 'Event log files directory'
|
-d --directory=[DIRECTORY] 'Directory of multiple .evtx files'
|
||||||
-s --statistics 'Prints statistics for event logs'
|
-s --statistics 'Prints statistics of event IDs'
|
||||||
-t --threadnum=[NUM] 'Thread number'
|
-t --threadnum=[NUM] 'Thread number (default: optimal number for performance)'
|
||||||
--contributors 'Prints the list of contributors'";
|
--contributors 'Prints the list of contributors'";
|
||||||
App::new(&program)
|
App::new(&program)
|
||||||
.about("hayabusa. Aiming to be the world's greatest Windows event log analysis tool!")
|
.about("Hayabusa: Aiming to be the world's greatest Windows event log analysis tool!")
|
||||||
.version("1.0.0")
|
.version("1.0.0")
|
||||||
.author("Author name Yamato-Security(https://github.com/Yamato-Security/hayabusa)")
|
.author("Yamato-Security(https://github.com/Yamato-Security/hayabusa)")
|
||||||
.setting(AppSettings::VersionlessSubcommands)
|
.setting(AppSettings::VersionlessSubcommands)
|
||||||
.usage(usages)
|
.usage(usages)
|
||||||
.args_from_usage(usages)
|
.args_from_usage(usages)
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ impl Detection {
|
|||||||
// ruleファイルのパースに失敗した場合はエラー出力
|
// ruleファイルのパースに失敗した場合はエラー出力
|
||||||
err_msgs_result.err().iter().for_each(|err_msgs| {
|
err_msgs_result.err().iter().for_each(|err_msgs| {
|
||||||
let errmsg_body =
|
let errmsg_body =
|
||||||
format!("Failed to parse Rule file. (FilePath : {})", rule.rulepath);
|
format!("Failed to parse rule file. (FilePath : {})", rule.rulepath);
|
||||||
AlertMessage::warn(&mut std::io::stdout().lock(), errmsg_body).ok();
|
AlertMessage::warn(&mut std::io::stdout().lock(), errmsg_body).ok();
|
||||||
|
|
||||||
err_msgs.iter().for_each(|err_msg| {
|
err_msgs.iter().for_each(|err_msg| {
|
||||||
@@ -145,8 +145,8 @@ impl Detection {
|
|||||||
|
|
||||||
pub fn print_unique_results(&self) {
|
pub fn print_unique_results(&self) {
|
||||||
let rules = &self.rules;
|
let rules = &self.rules;
|
||||||
let levellabel = Vec::from(["Critical", "High", "Medium", "Low", "Info", "Undeifned"]);
|
let levellabel = Vec::from(["Critical", "High", "Medium", "Low", "Info", "Undefined"]);
|
||||||
// levclcounts is [(Undeifned), (Info), (Low),(Medium),(High),(Critical)]
|
// levels are [(Undeifned), (Info), (Low),(Medium),(High),(Critical)]
|
||||||
let mut levelcounts = Vec::from([0, 0, 0, 0, 0, 0]);
|
let mut levelcounts = Vec::from([0, 0, 0, 0, 0, 0]);
|
||||||
for rule in rules.into_iter() {
|
for rule in rules.into_iter() {
|
||||||
if rule.check_exist_countdata() {
|
if rule.check_exist_countdata() {
|
||||||
@@ -165,10 +165,10 @@ impl Detection {
|
|||||||
let mut total_unique = 0;
|
let mut total_unique = 0;
|
||||||
levelcounts.reverse();
|
levelcounts.reverse();
|
||||||
for (i, value) in levelcounts.iter().enumerate() {
|
for (i, value) in levelcounts.iter().enumerate() {
|
||||||
println!("{} alerts {}", levellabel[i], value);
|
println!("{} alerts: {}", levellabel[i], value);
|
||||||
total_unique += value;
|
total_unique += value;
|
||||||
}
|
}
|
||||||
println!("Unique Events Detected: {}", total_unique);
|
println!("Unique events detected: {}", total_unique);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 複数のイベントレコードに対して、ルールを1個実行します。
|
// 複数のイベントレコードに対して、ルールを1個実行します。
|
||||||
@@ -246,12 +246,12 @@ impl Detection {
|
|||||||
) {
|
) {
|
||||||
let mut total = parseerror_count + ignore_count;
|
let mut total = parseerror_count + ignore_count;
|
||||||
rc.into_iter().for_each(|(key, value)| {
|
rc.into_iter().for_each(|(key, value)| {
|
||||||
println!("{} Rules: {}", key, value);
|
println!("{} rules: {}", key, value);
|
||||||
total += value;
|
total += value;
|
||||||
});
|
});
|
||||||
println!("Ignored Rule Count: {}", ignore_count);
|
println!("Ignored rules: {}", ignore_count);
|
||||||
println!("Rule Parse Errors Count: {}", parseerror_count);
|
println!("Rule parsing errors: {}", parseerror_count);
|
||||||
println!("Total Detection Rules: {}", total);
|
println!("Total detection rules: {}", total);
|
||||||
println!("");
|
println!("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ impl AggegationConditionCompiler {
|
|||||||
let result = self.compile_body(condition_str);
|
let result = self.compile_body(condition_str);
|
||||||
if let Result::Err(msg) = result {
|
if let Result::Err(msg) = result {
|
||||||
return Result::Err(format!(
|
return Result::Err(format!(
|
||||||
"aggregation condition parse error has occurred. {}",
|
"An aggregation condition parse error has occurred. {}",
|
||||||
msg
|
msg
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
@@ -137,7 +137,7 @@ impl AggegationConditionCompiler {
|
|||||||
) -> Result<Option<AggregationParseInfo>, String> {
|
) -> Result<Option<AggregationParseInfo>, String> {
|
||||||
if tokens.is_empty() {
|
if tokens.is_empty() {
|
||||||
// パイプしか無いのはおかしいのでエラー
|
// パイプしか無いのはおかしいのでエラー
|
||||||
return Result::Err("There are no strings after pipe(|).".to_string());
|
return Result::Err("There are no strings after the pipe(|).".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut token_ite = tokens.into_iter();
|
let mut token_ite = tokens.into_iter();
|
||||||
@@ -150,14 +150,14 @@ impl AggegationConditionCompiler {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// いろんなパターンがあるので難しいが、countというキーワードしか使えないことを説明しておく。
|
// いろんなパターンがあるので難しいが、countというキーワードしか使えないことを説明しておく。
|
||||||
return Result::Err("aggregation condition can use count only.".to_string());
|
return Result::Err("The aggregation condition can only use count.".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
let token = token_ite.next();
|
let token = token_ite.next();
|
||||||
if token.is_none() {
|
if token.is_none() {
|
||||||
// 論理演算子がないのはだめ
|
// 論理演算子がないのはだめ
|
||||||
return Result::Err(
|
return Result::Err(
|
||||||
"count keyword needs compare operator and number like '> 3'".to_string(),
|
"The count keyword needs a compare operator and number like '> 3'".to_string(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,14 +168,18 @@ impl AggegationConditionCompiler {
|
|||||||
let after_by = token_ite.next();
|
let after_by = token_ite.next();
|
||||||
if after_by.is_none() {
|
if after_by.is_none() {
|
||||||
// BYの後に何もないのはだめ
|
// BYの後に何もないのはだめ
|
||||||
return Result::Err("by keyword needs field name like 'by EventID'".to_string());
|
return Result::Err(
|
||||||
|
"The by keyword needs a field name like 'by EventID'".to_string(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let AggregationConditionToken::KEYWORD(keyword) = after_by.unwrap() {
|
if let AggregationConditionToken::KEYWORD(keyword) = after_by.unwrap() {
|
||||||
by_field_name = Option::Some(keyword);
|
by_field_name = Option::Some(keyword);
|
||||||
token_ite.next()
|
token_ite.next()
|
||||||
} else {
|
} else {
|
||||||
return Result::Err("by keyword needs field name like 'by EventID'".to_string());
|
return Result::Err(
|
||||||
|
"The by keyword needs a field name like 'by EventID'".to_string(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Option::Some(token)
|
Option::Some(token)
|
||||||
@@ -185,14 +189,14 @@ impl AggegationConditionCompiler {
|
|||||||
if token.is_none() {
|
if token.is_none() {
|
||||||
// 論理演算子がないのはだめ
|
// 論理演算子がないのはだめ
|
||||||
return Result::Err(
|
return Result::Err(
|
||||||
"count keyword needs compare operator and number like '> 3'".to_string(),
|
"The count keyword needs a compare operator and number like '> 3'".to_string(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let cmp_token = token.unwrap();
|
let cmp_token = token.unwrap();
|
||||||
if !self.is_cmp_op(&cmp_token) {
|
if !self.is_cmp_op(&cmp_token) {
|
||||||
return Result::Err(
|
return Result::Err(
|
||||||
"count keyword needs compare operator and number like '> 3'".to_string(),
|
"The count keyword needs a compare operator and number like '> 3'".to_string(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,17 +205,17 @@ impl AggegationConditionCompiler {
|
|||||||
let number: Result<i32, _> = number.parse();
|
let number: Result<i32, _> = number.parse();
|
||||||
if number.is_err() {
|
if number.is_err() {
|
||||||
// 比較演算子の後に数値が無い。
|
// 比較演算子の後に数値が無い。
|
||||||
return Result::Err("compare operator needs a number like '> 3'.".to_string());
|
return Result::Err("The compare operator needs a number like '> 3'.".to_string());
|
||||||
} else {
|
} else {
|
||||||
number.unwrap()
|
number.unwrap()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 比較演算子の後に数値が無い。
|
// 比較演算子の後に数値が無い。
|
||||||
return Result::Err("compare operator needs a number like '> 3'.".to_string());
|
return Result::Err("The compare operator needs a number like '> 3'.".to_string());
|
||||||
};
|
};
|
||||||
|
|
||||||
if token_ite.next().is_some() {
|
if token_ite.next().is_some() {
|
||||||
return Result::Err("unnecessary word was found.".to_string());
|
return Result::Err("An unnecessary word was found.".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
let info = AggregationParseInfo {
|
let info = AggregationParseInfo {
|
||||||
@@ -379,7 +383,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(true, result.is_err());
|
assert_eq!(true, result.is_err());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
"aggregation condition parse error has occurred. There are no strings after pipe(|)."
|
"An aggregation condition parse error has occurred. There are no strings after the pipe(|)."
|
||||||
.to_string(),
|
.to_string(),
|
||||||
result.unwrap_err()
|
result.unwrap_err()
|
||||||
);
|
);
|
||||||
@@ -393,7 +397,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(true, result.is_err());
|
assert_eq!(true, result.is_err());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
"aggregation condition parse error has occurred. An unusable character was found."
|
"An aggregation condition parse error has occurred. An unusable character was found."
|
||||||
.to_string(),
|
.to_string(),
|
||||||
result.unwrap_err()
|
result.unwrap_err()
|
||||||
);
|
);
|
||||||
@@ -407,7 +411,7 @@ mod tests {
|
|||||||
compiler.compile("select1 or select2 | by count( hogehoge) by snsn > 3".to_string());
|
compiler.compile("select1 or select2 | by count( hogehoge) by snsn > 3".to_string());
|
||||||
|
|
||||||
assert_eq!(true, result.is_err());
|
assert_eq!(true, result.is_err());
|
||||||
assert_eq!("aggregation condition parse error has occurred. aggregation condition can use count only.".to_string(),result.unwrap_err());
|
assert_eq!("An aggregation condition parse error has occurred. The aggregation condition can only use count.".to_string(),result.unwrap_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -417,7 +421,7 @@ mod tests {
|
|||||||
let result = compiler.compile("select1 or select2 | count( hogehoge) 3".to_string());
|
let result = compiler.compile("select1 or select2 | count( hogehoge) 3".to_string());
|
||||||
|
|
||||||
assert_eq!(true, result.is_err());
|
assert_eq!(true, result.is_err());
|
||||||
assert_eq!("aggregation condition parse error has occurred. count keyword needs compare operator and number like '> 3'".to_string(),result.unwrap_err());
|
assert_eq!("An aggregation condition parse error has occurred. The count keyword needs a compare operator and number like '> 3'".to_string(),result.unwrap_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -427,7 +431,7 @@ mod tests {
|
|||||||
let result = compiler.compile("select1 or select2 | count( hogehoge) by".to_string());
|
let result = compiler.compile("select1 or select2 | count( hogehoge) by".to_string());
|
||||||
|
|
||||||
assert_eq!(true, result.is_err());
|
assert_eq!(true, result.is_err());
|
||||||
assert_eq!("aggregation condition parse error has occurred. by keyword needs field name like 'by EventID'".to_string(),result.unwrap_err());
|
assert_eq!("An aggregation condition parse error has occurred. The by keyword needs a field name like 'by EventID'".to_string(),result.unwrap_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -438,7 +442,7 @@ mod tests {
|
|||||||
compiler.compile("select1 or select2 | count( hogehoge ) by hoe >".to_string());
|
compiler.compile("select1 or select2 | count( hogehoge ) by hoe >".to_string());
|
||||||
|
|
||||||
assert_eq!(true, result.is_err());
|
assert_eq!(true, result.is_err());
|
||||||
assert_eq!("aggregation condition parse error has occurred. compare operator needs a number like '> 3'.".to_string(),result.unwrap_err());
|
assert_eq!("An aggregation condition parse error has occurred. The compare operator needs a number like '> 3'.".to_string(),result.unwrap_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -450,7 +454,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(true, result.is_err());
|
assert_eq!(true, result.is_err());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
"aggregation condition parse error has occurred. unnecessary word was found."
|
"An aggregation condition parse error has occurred. An unnecessary word was found."
|
||||||
.to_string(),
|
.to_string(),
|
||||||
result.unwrap_err()
|
result.unwrap_err()
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ impl ConditionCompiler {
|
|||||||
|
|
||||||
let result = self.compile_condition_body(condition_str, name_2_node);
|
let result = self.compile_condition_body(condition_str, name_2_node);
|
||||||
if let Result::Err(msg) = result {
|
if let Result::Err(msg) = result {
|
||||||
return Result::Err(format!("condition parse error has occured. {}", msg));
|
return Result::Err(format!("A condition parse error has occured. {}", msg));
|
||||||
} else {
|
} else {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -269,7 +269,7 @@ impl ConditionCompiler {
|
|||||||
}
|
}
|
||||||
// 最後までついても対応する右括弧が見つからないことを表している
|
// 最後までついても対応する右括弧が見つからないことを表している
|
||||||
if left_cnt != right_cnt {
|
if left_cnt != right_cnt {
|
||||||
return Result::Err("expected ')'. but not found.".to_string());
|
return Result::Err("')' was expected but not found.".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ここで再帰的に呼び出す。
|
// ここで再帰的に呼び出す。
|
||||||
@@ -284,7 +284,7 @@ impl ConditionCompiler {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
if is_right_left {
|
if is_right_left {
|
||||||
return Result::Err("expected '('. but not found.".to_string());
|
return Result::Err("'(' was expected but not found.".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result::Ok(ret);
|
return Result::Ok(ret);
|
||||||
@@ -294,7 +294,7 @@ impl ConditionCompiler {
|
|||||||
fn parse_and_or_operator(&self, tokens: Vec<ConditionToken>) -> Result<ConditionToken, String> {
|
fn parse_and_or_operator(&self, tokens: Vec<ConditionToken>) -> Result<ConditionToken, String> {
|
||||||
if tokens.len() == 0 {
|
if tokens.len() == 0 {
|
||||||
// 長さ0は呼び出してはいけない
|
// 長さ0は呼び出してはいけない
|
||||||
return Result::Err("unknown error.".to_string());
|
return Result::Err("Unknown error.".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
// まず、selection1 and not selection2みたいな式のselection1やnot selection2のように、ANDやORでつながるトークンをまとめる。
|
// まず、selection1 and not selection2みたいな式のselection1やnot selection2のように、ANDやORでつながるトークンをまとめる。
|
||||||
@@ -302,7 +302,7 @@ impl ConditionCompiler {
|
|||||||
|
|
||||||
// 先頭又は末尾がAND/ORなのはだめ
|
// 先頭又は末尾がAND/ORなのはだめ
|
||||||
if self.is_logical(&tokens[0]) || self.is_logical(&tokens[tokens.len() - 1]) {
|
if self.is_logical(&tokens[0]) || self.is_logical(&tokens[tokens.len() - 1]) {
|
||||||
return Result::Err("illegal Logical Operator(and, or) was found.".to_string());
|
return Result::Err("An illegal logical operator(and, or) was found.".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
// OperandContainerとLogicalOperator(AndとOR)が交互に並んでいるので、それぞれリストに投入
|
// OperandContainerとLogicalOperator(AndとOR)が交互に並んでいるので、それぞれリストに投入
|
||||||
@@ -311,7 +311,9 @@ impl ConditionCompiler {
|
|||||||
for (i, token) in tokens.into_iter().enumerate() {
|
for (i, token) in tokens.into_iter().enumerate() {
|
||||||
if (i % 2 == 1) != self.is_logical(&token) {
|
if (i % 2 == 1) != self.is_logical(&token) {
|
||||||
// インデックスが奇数の時はLogicalOperatorで、インデックスが偶数のときはOperandContainerになる
|
// インデックスが奇数の時はLogicalOperatorで、インデックスが偶数のときはOperandContainerになる
|
||||||
return Result::Err("The use of logical operator(and, or) was wrong.".to_string());
|
return Result::Err(
|
||||||
|
"The use of a logical operator(and, or) was wrong.".to_string(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if i % 2 == 0 {
|
if i % 2 == 0 {
|
||||||
@@ -354,21 +356,21 @@ impl ConditionCompiler {
|
|||||||
// 上記の通り、3つ以上入っていることはないはず。
|
// 上記の通り、3つ以上入っていることはないはず。
|
||||||
if sub_tokens.len() >= 3 {
|
if sub_tokens.len() >= 3 {
|
||||||
return Result::Err(
|
return Result::Err(
|
||||||
"unknown error. maybe it's because there are multiple name of selection node."
|
"Unknown error. Maybe it is because there are multiple names of selection nodes."
|
||||||
.to_string(),
|
.to_string(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0はありえないはず
|
// 0はありえないはず
|
||||||
if sub_tokens.len() == 0 {
|
if sub_tokens.len() == 0 {
|
||||||
return Result::Err("unknown error.".to_string());
|
return Result::Err("Unknown error.".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1つだけ入っている場合、NOTはありえない。
|
// 1つだけ入っている場合、NOTはありえない。
|
||||||
if sub_tokens.len() == 1 {
|
if sub_tokens.len() == 1 {
|
||||||
let operand_subtoken = sub_tokens.into_iter().next().unwrap();
|
let operand_subtoken = sub_tokens.into_iter().next().unwrap();
|
||||||
if let ConditionToken::Not = operand_subtoken {
|
if let ConditionToken::Not = operand_subtoken {
|
||||||
return Result::Err("illegal not was found.".to_string());
|
return Result::Err("An illegal not was found.".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result::Ok(operand_subtoken);
|
return Result::Ok(operand_subtoken);
|
||||||
@@ -380,14 +382,14 @@ impl ConditionCompiler {
|
|||||||
let second_token = sub_tokens_ite.next().unwrap();
|
let second_token = sub_tokens_ite.next().unwrap();
|
||||||
if let ConditionToken::Not = first_token {
|
if let ConditionToken::Not = first_token {
|
||||||
if let ConditionToken::Not = second_token {
|
if let ConditionToken::Not = second_token {
|
||||||
return Result::Err("not is continuous.".to_string());
|
return Result::Err("Not is continuous.".to_string());
|
||||||
} else {
|
} else {
|
||||||
let not_container = ConditionToken::NotContainer(vec![second_token]);
|
let not_container = ConditionToken::NotContainer(vec![second_token]);
|
||||||
return Result::Ok(not_container);
|
return Result::Ok(not_container);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Result::Err(
|
return Result::Err(
|
||||||
"unknown error. maybe it's because there are multiple name of selection node."
|
"Unknown error. Maybe it is because there are multiple names of selection nodes."
|
||||||
.to_string(),
|
.to_string(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -450,7 +452,7 @@ impl ConditionCompiler {
|
|||||||
// NotSelectionNodeに変換
|
// NotSelectionNodeに変換
|
||||||
if let ConditionToken::NotContainer(sub_tokens) = token {
|
if let ConditionToken::NotContainer(sub_tokens) = token {
|
||||||
if sub_tokens.len() > 1 {
|
if sub_tokens.len() > 1 {
|
||||||
return Result::Err("unknown error".to_string());
|
return Result::Err("Unknown error".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
let select_sub_node =
|
let select_sub_node =
|
||||||
@@ -459,7 +461,7 @@ impl ConditionCompiler {
|
|||||||
return Result::Ok(Box::new(select_not_node));
|
return Result::Ok(Box::new(select_not_node));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result::Err("unknown error".to_string());
|
return Result::Err("Unknown error".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ConditionTokenがAndまたはOrTokenならばTrue
|
/// ConditionTokenがAndまたはOrTokenならばTrue
|
||||||
@@ -549,7 +551,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
Err(_rec) => {
|
Err(_rec) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -595,7 +597,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_rec) => {
|
Err(_rec) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -642,7 +644,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_rec) => {
|
Err(_rec) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1204,7 +1206,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
rule_node.init(),
|
rule_node.init(),
|
||||||
Err(vec![
|
Err(vec![
|
||||||
"There are no condition node under detection.".to_string()
|
"There is no condition node under detection.".to_string()
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1226,7 +1228,9 @@ mod tests {
|
|||||||
|
|
||||||
check_rule_parse_error(
|
check_rule_parse_error(
|
||||||
rule_str,
|
rule_str,
|
||||||
vec!["condition parse error has occured. An unusable character was found.".to_string()],
|
vec![
|
||||||
|
"A condition parse error has occured. An unusable character was found.".to_string(),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1247,7 +1251,9 @@ mod tests {
|
|||||||
|
|
||||||
check_rule_parse_error(
|
check_rule_parse_error(
|
||||||
rule_str,
|
rule_str,
|
||||||
vec!["condition parse error has occured. expected ')'. but not found.".to_string()],
|
vec![
|
||||||
|
"A condition parse error has occured. ')' was expected but not found.".to_string(),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1268,7 +1274,9 @@ mod tests {
|
|||||||
|
|
||||||
check_rule_parse_error(
|
check_rule_parse_error(
|
||||||
rule_str,
|
rule_str,
|
||||||
vec!["condition parse error has occured. expected '('. but not found.".to_string()],
|
vec![
|
||||||
|
"A condition parse error has occured. '(' was expected but not found.".to_string(),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1289,7 +1297,9 @@ mod tests {
|
|||||||
|
|
||||||
check_rule_parse_error(
|
check_rule_parse_error(
|
||||||
rule_str,
|
rule_str,
|
||||||
vec!["condition parse error has occured. expected ')'. but not found.".to_string()],
|
vec![
|
||||||
|
"A condition parse error has occured. ')' was expected but not found.".to_string(),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1308,7 +1318,7 @@ mod tests {
|
|||||||
output: 'Service name : %param1%¥nMessage : Event Log Service Stopped¥nResults: Selective event log manipulation may follow this event.'
|
output: 'Service name : %param1%¥nMessage : Event Log Service Stopped¥nResults: Selective event log manipulation may follow this event.'
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
check_rule_parse_error(rule_str,vec!["condition parse error has occured. unknown error. maybe it\'s because there are multiple name of selection node.".to_string()]);
|
check_rule_parse_error(rule_str,vec!["A condition parse error has occured. Unknown error. Maybe it is because there are multiple names of selection nodes.".to_string()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -1329,7 +1339,7 @@ mod tests {
|
|||||||
check_rule_parse_error(
|
check_rule_parse_error(
|
||||||
rule_str,
|
rule_str,
|
||||||
vec![
|
vec![
|
||||||
"condition parse error has occured. illegal Logical Operator(and, or) was found."
|
"A condition parse error has occured. An illegal logical operator(and, or) was found."
|
||||||
.to_string(),
|
.to_string(),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -1353,7 +1363,7 @@ mod tests {
|
|||||||
check_rule_parse_error(
|
check_rule_parse_error(
|
||||||
rule_str,
|
rule_str,
|
||||||
vec![
|
vec![
|
||||||
"condition parse error has occured. illegal Logical Operator(and, or) was found."
|
"A condition parse error has occured. An illegal logical operator(and, or) was found."
|
||||||
.to_string(),
|
.to_string(),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -1374,7 +1384,7 @@ mod tests {
|
|||||||
output: 'Service name : %param1%¥nMessage : Event Log Service Stopped¥nResults: Selective event log manipulation may follow this event.'
|
output: 'Service name : %param1%¥nMessage : Event Log Service Stopped¥nResults: Selective event log manipulation may follow this event.'
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
check_rule_parse_error(rule_str,vec!["condition parse error has occured. The use of logical operator(and, or) was wrong.".to_string()]);
|
check_rule_parse_error(rule_str,vec!["A condition parse error has occured. The use of a logical operator(and, or) was wrong.".to_string()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -1394,7 +1404,7 @@ mod tests {
|
|||||||
|
|
||||||
check_rule_parse_error(
|
check_rule_parse_error(
|
||||||
rule_str,
|
rule_str,
|
||||||
vec!["condition parse error has occured. illegal not was found.".to_string()],
|
vec!["A condition parse error has occured. An illegal not was found.".to_string()],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1415,7 +1425,7 @@ mod tests {
|
|||||||
|
|
||||||
check_rule_parse_error(
|
check_rule_parse_error(
|
||||||
rule_str,
|
rule_str,
|
||||||
vec!["condition parse error has occured. not is continuous.".to_string()],
|
vec!["A condition parse error has occured. Not is continuous.".to_string()],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ impl TimeFrameInfo {
|
|||||||
} else {
|
} else {
|
||||||
AlertMessage::alert(
|
AlertMessage::alert(
|
||||||
&mut std::io::stderr().lock(),
|
&mut std::io::stderr().lock(),
|
||||||
format!("timeframe is invalid.input value:{}", value),
|
format!("Timeframe is invalid. Input value:{}", value),
|
||||||
)
|
)
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
@@ -207,7 +207,7 @@ pub fn get_sec_timeframe(timeframe: &Option<TimeFrameInfo>) -> Option<i64> {
|
|||||||
Err(err) => {
|
Err(err) => {
|
||||||
AlertMessage::alert(
|
AlertMessage::alert(
|
||||||
&mut std::io::stderr().lock(),
|
&mut std::io::stderr().lock(),
|
||||||
format!("timeframe num is invalid. timeframe.{}", err),
|
format!("Timeframe number is invalid. timeframe.{}", err),
|
||||||
)
|
)
|
||||||
.ok();
|
.ok();
|
||||||
return Option::None;
|
return Option::None;
|
||||||
@@ -755,7 +755,7 @@ mod tests {
|
|||||||
let mut rule_node = create_rule("testpath".to_string(), test);
|
let mut rule_node = create_rule("testpath".to_string(), test);
|
||||||
let error_checker = rule_node.init();
|
let error_checker = rule_node.init();
|
||||||
if error_checker.is_err() {
|
if error_checker.is_err() {
|
||||||
assert!(false, "failed to init rulenode");
|
assert!(false, "Failed to init rulenode");
|
||||||
}
|
}
|
||||||
for record_str in records_str {
|
for record_str in records_str {
|
||||||
match serde_json::from_str(record_str) {
|
match serde_json::from_str(record_str) {
|
||||||
@@ -769,7 +769,7 @@ mod tests {
|
|||||||
assert_eq!(result, &true);
|
assert_eq!(result, &true);
|
||||||
}
|
}
|
||||||
Err(_rec) => {
|
Err(_rec) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ impl LeafMatcher for MinlengthMatcher {
|
|||||||
let min_length = select_value.as_i64();
|
let min_length = select_value.as_i64();
|
||||||
if min_length.is_none() {
|
if min_length.is_none() {
|
||||||
let errmsg = format!(
|
let errmsg = format!(
|
||||||
"min_length value should be Integer. [key:{}]",
|
"min_length value should be an integer. [key:{}]",
|
||||||
utils::concat_selection_key(key_list)
|
utils::concat_selection_key(key_list)
|
||||||
);
|
);
|
||||||
return Result::Err(vec![errmsg]);
|
return Result::Err(vec![errmsg]);
|
||||||
@@ -99,7 +99,7 @@ impl LeafMatcher for RegexesFileMatcher {
|
|||||||
};
|
};
|
||||||
if value.is_none() {
|
if value.is_none() {
|
||||||
let errmsg = format!(
|
let errmsg = format!(
|
||||||
"regexes value should be String. [key:{}]",
|
"regexes value should be a string. [key:{}]",
|
||||||
utils::concat_selection_key(key_list)
|
utils::concat_selection_key(key_list)
|
||||||
);
|
);
|
||||||
return Result::Err(vec![errmsg]);
|
return Result::Err(vec![errmsg]);
|
||||||
@@ -158,7 +158,7 @@ impl LeafMatcher for AllowlistFileMatcher {
|
|||||||
};
|
};
|
||||||
if value.is_none() {
|
if value.is_none() {
|
||||||
let errmsg = format!(
|
let errmsg = format!(
|
||||||
"allowlist value should be String. [key:{}]",
|
"allowlist value should be a string. [key:{}]",
|
||||||
utils::concat_selection_key(key_list)
|
utils::concat_selection_key(key_list)
|
||||||
);
|
);
|
||||||
return Result::Err(vec![errmsg]);
|
return Result::Err(vec![errmsg]);
|
||||||
@@ -253,7 +253,7 @@ impl LeafMatcher for DefaultMatcher {
|
|||||||
};
|
};
|
||||||
if yaml_value.is_none() {
|
if yaml_value.is_none() {
|
||||||
let errmsg = format!(
|
let errmsg = format!(
|
||||||
"unknown error occured. [key:{}]",
|
"An unknown error occured. [key:{}]",
|
||||||
utils::concat_selection_key(key_list)
|
utils::concat_selection_key(key_list)
|
||||||
);
|
);
|
||||||
return Result::Err(vec![errmsg]);
|
return Result::Err(vec![errmsg]);
|
||||||
@@ -275,7 +275,7 @@ impl LeafMatcher for DefaultMatcher {
|
|||||||
};
|
};
|
||||||
if pipe_element.is_none() {
|
if pipe_element.is_none() {
|
||||||
let errmsg = format!(
|
let errmsg = format!(
|
||||||
"unknown pipe element was specified. key:{}",
|
"An unknown pipe element was specified. key:{}",
|
||||||
utils::concat_selection_key(key_list)
|
utils::concat_selection_key(key_list)
|
||||||
);
|
);
|
||||||
return Result::Err(vec![errmsg]);
|
return Result::Err(vec![errmsg]);
|
||||||
@@ -286,7 +286,7 @@ impl LeafMatcher for DefaultMatcher {
|
|||||||
if self.pipes.len() >= 2 {
|
if self.pipes.len() >= 2 {
|
||||||
// 現状では複数のパイプは対応していない
|
// 現状では複数のパイプは対応していない
|
||||||
let errmsg = format!(
|
let errmsg = format!(
|
||||||
"multiple pipe element can't be used. key:{}",
|
"Multiple pipe elements cannot be used. key:{}",
|
||||||
utils::concat_selection_key(key_list)
|
utils::concat_selection_key(key_list)
|
||||||
);
|
);
|
||||||
return Result::Err(vec![errmsg]);
|
return Result::Err(vec![errmsg]);
|
||||||
@@ -309,7 +309,7 @@ impl LeafMatcher for DefaultMatcher {
|
|||||||
let re_result = Regex::new(&pattern);
|
let re_result = Regex::new(&pattern);
|
||||||
if re_result.is_err() {
|
if re_result.is_err() {
|
||||||
let errmsg = format!(
|
let errmsg = format!(
|
||||||
"cannot parse regex. [regex:{}, key:{}]",
|
"Cannot parse regex. [regex:{}, key:{}]",
|
||||||
pattern,
|
pattern,
|
||||||
utils::concat_selection_key(key_list)
|
utils::concat_selection_key(key_list)
|
||||||
);
|
);
|
||||||
@@ -779,7 +779,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -846,7 +846,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -880,7 +880,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -913,7 +913,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -946,7 +946,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -980,7 +980,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1014,7 +1014,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1048,7 +1048,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1082,7 +1082,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1116,7 +1116,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1149,7 +1149,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1186,7 +1186,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1223,7 +1223,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1259,7 +1259,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1304,7 +1304,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_rec) => {
|
Err(_rec) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1349,7 +1349,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_rec) => {
|
Err(_rec) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1394,7 +1394,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_rec) => {
|
Err(_rec) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1439,7 +1439,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_rec) => {
|
Err(_rec) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1484,7 +1484,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_rec) => {
|
Err(_rec) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1529,7 +1529,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_rec) => {
|
Err(_rec) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1562,7 +1562,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1595,7 +1595,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1628,7 +1628,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1721,7 +1721,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1756,7 +1756,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1791,7 +1791,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1826,7 +1826,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ impl DetectionNode {
|
|||||||
let mut keys = self.name_to_selection.keys().clone();
|
let mut keys = self.name_to_selection.keys().clone();
|
||||||
if keys.len() >= 2 {
|
if keys.len() >= 2 {
|
||||||
return Result::Err(vec![
|
return Result::Err(vec![
|
||||||
"There are no condition node under detection.".to_string()
|
"There is no condition node under detection.".to_string()
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +191,7 @@ impl DetectionNode {
|
|||||||
fn parse_name_to_selection(&mut self, detection_yaml: &Yaml) -> Result<(), Vec<String>> {
|
fn parse_name_to_selection(&mut self, detection_yaml: &Yaml) -> Result<(), Vec<String>> {
|
||||||
let detection_hash = detection_yaml.as_hash();
|
let detection_hash = detection_yaml.as_hash();
|
||||||
if detection_hash.is_none() {
|
if detection_hash.is_none() {
|
||||||
return Result::Err(vec!["not found detection node".to_string()]);
|
return Result::Err(vec!["Detection node was not found.".to_string()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// selectionをパースする。
|
// selectionをパースする。
|
||||||
@@ -229,7 +229,7 @@ impl DetectionNode {
|
|||||||
// selectionノードが無いのはエラー
|
// selectionノードが無いのはエラー
|
||||||
if self.name_to_selection.len() == 0 {
|
if self.name_to_selection.len() == 0 {
|
||||||
return Result::Err(vec![
|
return Result::Err(vec![
|
||||||
"There are no selection node under detection.".to_string()
|
"There is no selection node under detection.".to_string()
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,7 +360,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -393,7 +393,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -426,7 +426,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -512,7 +512,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -574,7 +574,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -643,7 +643,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -690,7 +690,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -738,7 +738,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -805,7 +805,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -872,7 +872,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -921,7 +921,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_rec) => {
|
Err(_rec) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -943,7 +943,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
rule_node.init(),
|
rule_node.init(),
|
||||||
Err(vec![
|
Err(vec![
|
||||||
"unknown pipe element was specified. key:detection -> selection -> Channel|failed"
|
"An unknown pipe element was specified. key:detection -> selection -> Channel|failed"
|
||||||
.to_string()
|
.to_string()
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
@@ -962,7 +962,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rule_node.init(),
|
rule_node.init(),
|
||||||
Err(vec!["not found detection node".to_string()])
|
Err(vec!["Detection node was not found.".to_string()])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -997,7 +997,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
Err(_rec) => {
|
Err(_rec) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -392,7 +392,7 @@ impl SelectionNode for LeafSelectionNode {
|
|||||||
|
|
||||||
if self.select_value.is_badvalue() {
|
if self.select_value.is_badvalue() {
|
||||||
return Result::Err(vec![format!(
|
return Result::Err(vec![format!(
|
||||||
"Cannot parse yaml file. key:{}",
|
"Cannot parse yml file. key:{}",
|
||||||
utils::concat_selection_key(&match_key_list)
|
utils::concat_selection_key(&match_key_list)
|
||||||
)]);
|
)]);
|
||||||
}
|
}
|
||||||
@@ -446,7 +446,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -482,7 +482,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -517,7 +517,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -552,7 +552,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), true);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -587,7 +587,7 @@ mod tests {
|
|||||||
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
assert_eq!(rule_node.select(&"testpath".to_owned(), &recinfo), false);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
assert!(false, "failed to parse json record.");
|
assert!(false, "Failed to parse json record.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ pub fn check_allowlist(target: &str, regexes: &Vec<Regex>) -> bool {
|
|||||||
pub fn read_txt(filename: &str) -> Result<Vec<String>, String> {
|
pub fn read_txt(filename: &str) -> Result<Vec<String>, String> {
|
||||||
let f = File::open(filename);
|
let f = File::open(filename);
|
||||||
if f.is_err() {
|
if f.is_err() {
|
||||||
let errmsg = format!("cannot open file. [file:{}]", filename);
|
let errmsg = format!("Cannot open file. [file:{}]", filename);
|
||||||
return Result::Err(errmsg);
|
return Result::Err(errmsg);
|
||||||
}
|
}
|
||||||
let reader = BufReader::new(f.unwrap());
|
let reader = BufReader::new(f.unwrap());
|
||||||
@@ -62,7 +62,7 @@ pub fn read_txt(filename: &str) -> Result<Vec<String>, String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_csv(filename: &str) -> Result<Vec<Vec<String>>, String> {
|
pub fn read_csv(filename: &str) -> Result<Vec<Vec<String>>, String> {
|
||||||
let mut f = File::open(filename).expect("file not found!!!");
|
let mut f = File::open(filename).expect("File not found!!!");
|
||||||
let mut contents: String = String::new();
|
let mut contents: String = String::new();
|
||||||
let mut ret = vec![];
|
let mut ret = vec![];
|
||||||
let read_res = f.read_to_string(&mut contents);
|
let read_res = f.read_to_string(&mut contents);
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ fn main() {
|
|||||||
if !filepath.ends_with(".evtx") {
|
if !filepath.ends_with(".evtx") {
|
||||||
AlertMessage::alert(
|
AlertMessage::alert(
|
||||||
&mut std::io::stderr().lock(),
|
&mut std::io::stderr().lock(),
|
||||||
"--filepath is only accepted evtx file.".to_owned(),
|
"--filepath only accepts .evtx files.".to_owned(),
|
||||||
)
|
)
|
||||||
.ok();
|
.ok();
|
||||||
return;
|
return;
|
||||||
@@ -47,7 +47,7 @@ fn main() {
|
|||||||
if evtx_files.len() == 0 {
|
if evtx_files.len() == 0 {
|
||||||
AlertMessage::alert(
|
AlertMessage::alert(
|
||||||
&mut std::io::stderr().lock(),
|
&mut std::io::stderr().lock(),
|
||||||
"No exist evtx file.".to_owned(),
|
"No .evtx files were found.".to_owned(),
|
||||||
)
|
)
|
||||||
.ok();
|
.ok();
|
||||||
return;
|
return;
|
||||||
@@ -118,7 +118,7 @@ fn analysis_files(evtx_files: Vec<PathBuf>) {
|
|||||||
.value_of("level")
|
.value_of("level")
|
||||||
.unwrap_or("INFO")
|
.unwrap_or("INFO")
|
||||||
.to_uppercase();
|
.to_uppercase();
|
||||||
println!("Analyzing Event Files: {:?}", evtx_files.len());
|
println!("Analyzing event files: {:?}", evtx_files.len());
|
||||||
let rule_files = detection::Detection::parse_rule_files(
|
let rule_files = detection::Detection::parse_rule_files(
|
||||||
level,
|
level,
|
||||||
configs::CONFIG.read().unwrap().args.value_of("rules"),
|
configs::CONFIG.read().unwrap().args.value_of("rules"),
|
||||||
@@ -126,7 +126,7 @@ fn analysis_files(evtx_files: Vec<PathBuf>) {
|
|||||||
let mut detection = detection::Detection::new(rule_files);
|
let mut detection = detection::Detection::new(rule_files);
|
||||||
for evtx_file in evtx_files {
|
for evtx_file in evtx_files {
|
||||||
if configs::CONFIG.read().unwrap().args.is_present("verbose") {
|
if configs::CONFIG.read().unwrap().args.is_present("verbose") {
|
||||||
println!("check target evtx FilePath: {:?}", &evtx_file);
|
println!("Checking target evtx FilePath: {:?}", &evtx_file);
|
||||||
}
|
}
|
||||||
detection = analysis_file(evtx_file, detection);
|
detection = analysis_file(evtx_file, detection);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ impl ParseYaml {
|
|||||||
AlertMessage::warn(
|
AlertMessage::warn(
|
||||||
&mut std::io::stdout().lock(),
|
&mut std::io::stdout().lock(),
|
||||||
format!(
|
format!(
|
||||||
"fail to parse as yaml: {}\n{} ",
|
"Failed to parse yml: {}\n{} ",
|
||||||
entry.path().display(),
|
entry.path().display(),
|
||||||
yaml_contents.unwrap_err()
|
yaml_contents.unwrap_err()
|
||||||
),
|
),
|
||||||
@@ -109,14 +109,14 @@ impl ParseYaml {
|
|||||||
return Option::None;
|
return Option::None;
|
||||||
}
|
}
|
||||||
self.rulecounter.insert(
|
self.rulecounter.insert(
|
||||||
yaml_doc["ruletype"].as_str().unwrap_or("other").to_string(),
|
yaml_doc["ruletype"].as_str().unwrap_or("Other").to_string(),
|
||||||
self.rulecounter
|
self.rulecounter
|
||||||
.get(&yaml_doc["ruletype"].as_str().unwrap_or("other").to_string())
|
.get(&yaml_doc["ruletype"].as_str().unwrap_or("Other").to_string())
|
||||||
.unwrap_or(&0)
|
.unwrap_or(&0)
|
||||||
+ 1,
|
+ 1,
|
||||||
);
|
);
|
||||||
if configs::CONFIG.read().unwrap().args.is_present("verbose") {
|
if configs::CONFIG.read().unwrap().args.is_present("verbose") {
|
||||||
println!("Loaded yml FilePath: {}", filepath);
|
println!("Loaded yml file path: {}", filepath);
|
||||||
}
|
}
|
||||||
// 指定されたレベルより低いルールは無視する
|
// 指定されたレベルより低いルールは無視する
|
||||||
let doc_level = &yaml_doc["level"]
|
let doc_level = &yaml_doc["level"]
|
||||||
|
|||||||
Reference in New Issue
Block a user