1- from datetime import datetime
2-
3- from sigma .rule import SigmaRule
1+ from datetime import date , timedelta
2+ import pytest
3+ from sigma .rule import SigmaRule , SigmaStatus
44from sigma .correlations import SigmaCorrelationRule
55from sigma .validators .sigmahq .status import (
66 SigmahqStatusToHighIssue ,
77 SigmahqStatusToHighValidator ,
88)
99
10+ # Constants for test parameters with min_days configuration
11+ TEST_PARAMS = [
12+ # (min_nolog, min_log, days_ago, status, has_regression_tests, expected_has_issue)
13+ # Default minimum days (60 for non-log, 15 for log)
14+ (60 , 15 , 1 , SigmaStatus .STABLE , False , True ), # New STABLE rule fails
15+ (60 , 15 , 60 , SigmaStatus .STABLE , False , True ), # Exactly at min_nolog=60 fails
16+ (60 , 15 , 61 , SigmaStatus .STABLE , False , False ), # Just over min_nolog=60 passes
17+ (30 , 15 , 1 , SigmaStatus .STABLE , False , True ), # New STABLE rule fails with min_nolog=30
18+ (30 , 15 , 29 , SigmaStatus .STABLE , False , True ), # Just under min_nolog=30 fails
19+ (30 , 15 , 30 , SigmaStatus .STABLE , False , True ), # Exactly at min_nolog=30 fails
20+ (60 , 15 , 29 , SigmaStatus .STABLE , True , False ), # Regression test rule passes
21+ (60 , 15 , 14 , SigmaStatus .STABLE , True , True ), # Log rule with regression under min_log=15
22+ (30 , 15 , 29 , SigmaStatus .TEST , True , False ), # TEST status always passes
23+ ]
1024
11- def test_validator_SigmahqStatusToHigh ():
12- validator = SigmahqStatusToHighValidator ()
13- detection_rule = SigmaRule .from_yaml (
14- """
15- title: Test
16- description: Test
17- status: stable
18- date: 1975-01-01
19- logsource:
20- category: test
21- detection:
22- sel:
23- candle|exists: true
24- condition: sel
25- """
25+
26+ def create_test_rule (days_ago , status , has_regression_tests ):
27+ """Helper function to create test rules."""
28+ date_str = (date .today () - timedelta (days = days_ago )).strftime ("%Y-%m-%d" )
29+
30+ yaml_content = f"""
31+ title: Test Rule
32+ status: { status .name .lower ()}
33+ date: { date_str }
34+ logsource:
35+ category: test
36+ product: windows
37+ detection:
38+ sel:
39+ candle|exists: true
40+ condition: sel
41+ """
42+
43+ if has_regression_tests :
44+ yaml_content += "\n regression_tests_path: regression/rule/test_rule.yml"
45+
46+ return SigmaRule .from_yaml (yaml_content )
47+
48+
49+ def create_correlation_rule (days_ago , status , has_regression_tests ):
50+ """Helper function to create correlation test rules."""
51+ date_str = (date .today () - timedelta (days = days_ago )).strftime ("%Y-%m-%d" )
52+
53+ yaml_content = f"""
54+ title: Test Correlation
55+ id: 12345678-1234-1234-1234-123456789012
56+ status: { status .name .lower ()}
57+ date: { date_str }
58+ logsource:
59+ category: correlation
60+ product: windows
61+ correlation:
62+ type: temporal
63+ rules:
64+ - 5638f7c0-ac70-491d-8465-2a65075e0d86
65+ timespan: 5m
66+ group-by:
67+ - ComputerName
68+ """
69+
70+ if has_regression_tests :
71+ yaml_content += "\n regression_tests_path: regression/rule/test_rule.yml"
72+
73+ return SigmaCorrelationRule .from_yaml (yaml_content )
74+
75+
76+ @pytest .mark .parametrize (
77+ "min_nolog, min_log, days_ago, status, has_regression_tests, expected_has_issue" , TEST_PARAMS
78+ )
79+ def test_status_validation_detection (
80+ min_nolog , min_log , days_ago , status , has_regression_tests , expected_has_issue
81+ ):
82+ """Test validation scenarios for detection rules with configurable minimum days."""
83+ rule = create_test_rule (days_ago , status , has_regression_tests )
84+
85+ validator = SigmahqStatusToHighValidator (
86+ min_days_for_nolog_rule = min_nolog , min_days_for_log_rule = min_log
2687 )
27- detection_rule .date = datetime .now ().date ()
28- assert validator .validate (detection_rule ) == [SigmahqStatusToHighIssue ([detection_rule ])]
2988
89+ if expected_has_issue :
90+ assert validator .validate (rule ) == [SigmahqStatusToHighIssue ([rule ])]
91+ else :
92+ assert validator .validate (rule ) == []
3093
31- def test_validator_SigmahqStatusToHigh_valid ():
32- validator = SigmahqStatusToHighValidator ()
33- detection_rule = SigmaRule .from_yaml (
34- """
35- title: Test
36- description: Test
37- status: stable
38- date: 1975-01-01
39- logsource:
40- category: test
41- detection:
42- sel:
43- candle|exists: true
44- condition: sel
45- """
94+
95+ @pytest .mark .parametrize (
96+ "min_nolog, min_log, days_ago, status, has_regression_tests, expected_has_issue" , TEST_PARAMS
97+ )
98+ def test_status_validation_correlation (
99+ min_nolog , min_log , days_ago , status , has_regression_tests , expected_has_issue
100+ ):
101+ """Test validation scenarios for correlation rules with configurable minimum days."""
102+ rule = create_correlation_rule (days_ago , status , has_regression_tests )
103+
104+ validator = SigmahqStatusToHighValidator (
105+ min_days_for_nolog_rule = min_nolog , min_days_for_log_rule = min_log
46106 )
47- assert validator .validate (detection_rule ) == []
107+ if expected_has_issue :
108+ assert validator .validate (rule ) == [SigmahqStatusToHighIssue ([rule ])]
109+ else :
110+ assert validator .validate (rule ) == []
111+
48112
113+ def test_rules_without_date ():
114+ """Test that rules without dates always pass validation."""
115+ # Test with different minimum days configurations
116+ validators = [
117+ SigmahqStatusToHighValidator (min_days_for_nolog_rule = 60 , min_days_for_log_rule = 15 ),
118+ SigmahqStatusToHighValidator (min_days_for_nolog_rule = 30 , min_days_for_log_rule = 15 ),
119+ ]
49120
50- def test_validator_SigmahqStatusToHigh_with_regression_valid ():
51- validator = SigmahqStatusToHighValidator ()
121+ # Test detection rule without date
52122 detection_rule = SigmaRule .from_yaml (
53123 """
54- title: Test
55- description: Test
56- status: test
57- date: 1975-01-01
58- logsource:
59- category: test
60- detection:
61- sel:
62- candle|exists: true
63- condition: sel
64- regression_tests_path: regression/rule/test_rule.yml
65- """
124+ title: Rule Without Date
125+ status: stable
126+ logsource:
127+ category: test
128+ detection:
129+ sel:
130+ candle|exists: true
131+ condition: sel
132+ """
66133 )
67- detection_rule .date = datetime .now ().date ()
68- assert validator .validate (detection_rule ) == []
69134
70-
71- def test_validator_SigmahqStatusToHigh_correlation ():
72- validator = SigmahqStatusToHighValidator ()
135+ # Test correlation rule without date
73136 correlation_rule = SigmaCorrelationRule .from_yaml (
74137 """
75- title: Test Correlation
76- id: 0e95725d-7320-415d-80f7-004da920fc11
138+ title: Correlation Rule Without Date
139+ id: 12345678-1234-1234-1234-123456789012
77140status: stable
141+ logsource:
142+ category: correlation
143+ product: windows
78144correlation:
79145 type: temporal
80146 rules:
@@ -84,17 +150,44 @@ def test_validator_SigmahqStatusToHigh_correlation():
84150 - ComputerName
85151"""
86152 )
87- correlation_rule .date = datetime .now ().date ()
88- assert validator .validate (correlation_rule ) == [SigmahqStatusToHighIssue ([correlation_rule ])]
153+
154+ # All validators should pass rules without dates
155+ for validator in validators :
156+ assert validator .validate (detection_rule ) == []
157+ assert validator .validate (correlation_rule ) == []
89158
90159
91- def test_validator_SigmahqStatusToHigh_correlation_valid ():
92- validator = SigmahqStatusToHighValidator ()
160+ def test_rules_without_status ():
161+ """Test that rules without dates always pass validation."""
162+ # Test with different minimum days configurations
163+ validators = [
164+ SigmahqStatusToHighValidator (min_days_for_nolog_rule = 60 , min_days_for_log_rule = 15 ),
165+ SigmahqStatusToHighValidator (min_days_for_nolog_rule = 30 , min_days_for_log_rule = 15 ),
166+ ]
167+
168+ # Test detection rule without date
169+ detection_rule = SigmaRule .from_yaml (
170+ """
171+ title: Rule Without Status
172+ date: 2030-01-01
173+ logsource:
174+ category: test
175+ detection:
176+ sel:
177+ candle|exists: true
178+ condition: sel
179+ """
180+ )
181+
182+ # Test correlation rule without date
93183 correlation_rule = SigmaCorrelationRule .from_yaml (
94184 """
95- title: Test Correlation
96- id: 0e95725d-7320-415d-80f7-004da920fc11
97- status: test
185+ title: Correlation Rule Without Status
186+ id: 12345678-1234-1234-1234-123456789012
187+ date: 2030-01-01
188+ logsource:
189+ category: correlation
190+ product: windows
98191correlation:
99192 type: temporal
100193 rules:
@@ -104,4 +197,8 @@ def test_validator_SigmahqStatusToHigh_correlation_valid():
104197 - ComputerName
105198"""
106199 )
107- assert validator .validate (correlation_rule ) == []
200+
201+ # All validators should pass rules without dates
202+ for validator in validators :
203+ assert validator .validate (detection_rule ) == []
204+ assert validator .validate (correlation_rule ) == []
0 commit comments