|
24 | 24 | //! conditions: |
25 | 25 | //! index: "windows" |
26 | 26 | //! rule_conditions: |
27 | | -//! - type: logsource_product |
| 27 | +//! - type: logsource |
28 | 28 | //! product: windows |
29 | 29 | //! "#; |
30 | 30 | //! |
@@ -873,30 +873,42 @@ pub struct TransformationConfig { |
873 | 873 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] |
874 | 874 | #[serde(tag = "type")] |
875 | 875 | pub enum RuleCondition { |
876 | | - /// Match rules by log source category. |
877 | | - #[serde(rename = "logsource_category")] |
878 | | - LogSourceCategory { category: String }, |
879 | | - |
880 | | - /// Match rules by log source product. |
881 | | - #[serde(rename = "logsource_product")] |
882 | | - LogSourceProduct { product: String }, |
883 | | - |
884 | | - /// Match rules by log source service. |
885 | | - #[serde(rename = "logsource_service")] |
886 | | - LogSourceService { service: String }, |
| 876 | + /// Match rules by log source attributes. |
| 877 | + /// |
| 878 | + /// Any combination of `category`, `product`, and `service` can be specified. |
| 879 | + /// Only the fields that are set are compared; unspecified fields are ignored. |
| 880 | + /// This mirrors pySigma's `LogsourceCondition`. |
| 881 | + #[serde(rename = "logsource")] |
| 882 | + LogSource { |
| 883 | + #[serde(default, skip_serializing_if = "Option::is_none")] |
| 884 | + category: Option<String>, |
| 885 | + #[serde(default, skip_serializing_if = "Option::is_none")] |
| 886 | + product: Option<String>, |
| 887 | + #[serde(default, skip_serializing_if = "Option::is_none")] |
| 888 | + service: Option<String>, |
| 889 | + }, |
887 | 890 | } |
888 | 891 |
|
889 | 892 | impl RuleCondition { |
890 | 893 | fn matches(&self, rule: &SigmaRule) -> bool { |
891 | 894 | match self { |
892 | | - Self::LogSourceCategory { category } => { |
893 | | - rule.logsource.category.as_deref() == Some(category) |
894 | | - } |
895 | | - Self::LogSourceProduct { product } => { |
896 | | - rule.logsource.product.as_deref() == Some(product) |
897 | | - } |
898 | | - Self::LogSourceService { service } => { |
899 | | - rule.logsource.service.as_deref() == Some(service) |
| 895 | + Self::LogSource { category, product, service } => { |
| 896 | + if let Some(cat) = category |
| 897 | + && rule.logsource.category.as_deref() != Some(cat) |
| 898 | + { |
| 899 | + return false; |
| 900 | + } |
| 901 | + if let Some(prod) = product |
| 902 | + && rule.logsource.product.as_deref() != Some(prod) |
| 903 | + { |
| 904 | + return false; |
| 905 | + } |
| 906 | + if let Some(svc) = service |
| 907 | + && rule.logsource.service.as_deref() != Some(svc) |
| 908 | + { |
| 909 | + return false; |
| 910 | + } |
| 911 | + true |
900 | 912 | } |
901 | 913 | } |
902 | 914 | } |
@@ -1134,7 +1146,7 @@ transformations: |
1134 | 1146 | type: field_name_prefix |
1135 | 1147 | prefix: "proc." |
1136 | 1148 | rule_conditions: |
1137 | | - - type: logsource_category |
| 1149 | + - type: logsource |
1138 | 1150 | category: process_creation |
1139 | 1151 | "#; |
1140 | 1152 |
|
@@ -1406,7 +1418,7 @@ transformations: |
1406 | 1418 | type: field_name_prefix |
1407 | 1419 | prefix: "proc." |
1408 | 1420 | rule_conditions: |
1409 | | - - type: logsource_product |
| 1421 | + - type: logsource |
1410 | 1422 | product: linux |
1411 | 1423 | "#; |
1412 | 1424 |
|
@@ -2423,7 +2435,7 @@ transformations: |
2423 | 2435 | type: field_name_prefix |
2424 | 2436 | prefix: "s." |
2425 | 2437 | rule_conditions: |
2426 | | - - type: logsource_service |
| 2438 | + - type: logsource |
2427 | 2439 | service: sysmon |
2428 | 2440 | "#; |
2429 | 2441 | let pipeline = ProcessingPipeline::from_yaml(yaml).unwrap(); |
|
0 commit comments