Skip to content

Commit e90fa55

Browse files
authored
Merge pull request #2342 from ggbecker/autotailor-validate-datastream-fields
autotailor: Add validation for variable names, rule IDs, and profile IDs
2 parents ac3ef59 + ef1d59d commit e90fa55

4 files changed

Lines changed: 378 additions & 20 deletions

File tree

tests/utils/autotailor_integration_test.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,17 @@ assert_exists 1 '/Benchmark/TestResult/rule-result[@idref="xccdf_com.example.www
112112
assert_exists 1 '/Benchmark/TestResult/rule-result[@idref="xccdf_com.example.www_rule_R3"]/result[text()="notselected"]'
113113
assert_exists 1 '/Benchmark/TestResult/rule-result[@idref="xccdf_com.example.www_rule_R4"]/result[text()="notselected"]'
114114

115+
# invalid selector for V1 should fail with a descriptive error
116+
! python3 $autotailor --id-namespace "com.example.www" --var-select V1=invalid $ds $original_profile 2>$stdout
117+
grep "Selector 'invalid' does not exist" $stdout
118+
119+
# invalid selector for V2 should fail with available selectors listed
120+
! python3 $autotailor --id-namespace "com.example.www" --var-select V2=invalid $ds $original_profile 2>$stdout
121+
grep "Available selectors" $stdout
122+
123+
# --no-validate bypasses selector validation
124+
python3 $autotailor --id-namespace "com.example.www" --no-validate --var-select V1=invalid $ds $original_profile > $tailoring
125+
115126
# use JSON tailoring (P1)
116127
python3 $autotailor $ds --id-namespace "com.example.www" --json-tailoring $json_tailoring > $tailoring
117128
$OSCAP xccdf eval --profile JSON_P1 --progress --tailoring-file $tailoring --results $result $ds

tests/utils/test_autotailor.py

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,146 @@ def test_get_datastream_uri():
135135
uri = t._get_datastream_uri()
136136
assert uri.startswith("file://")
137137
assert "relative/path/to/ds.xml" in uri
138+
139+
140+
def test_datastream_validator():
141+
"""Test that DataStreamValidator properly validates IDs."""
142+
ds_path = pathlib.Path(__file__).parent.joinpath("data_stream.xml")
143+
validator = autotailor.DataStreamValidator(str(ds_path))
144+
145+
# Test valid profile validation
146+
validator.validate_profile("xccdf_com.example.www_profile_P1")
147+
148+
# Test valid value validation
149+
validator.validate_value("xccdf_com.example.www_value_V1")
150+
validator.validate_value("xccdf_com.example.www_value_V2")
151+
152+
# Test valid rule validation
153+
validator.validate_rule("xccdf_com.example.www_rule_R1")
154+
validator.validate_rule("xccdf_com.example.www_rule_R2")
155+
validator.validate_rule("xccdf_com.example.www_rule_R3")
156+
validator.validate_rule("xccdf_com.example.www_rule_R4")
157+
158+
# Test valid group validation
159+
validator.validate_group("xccdf_com.example.www_group_G34")
160+
161+
# Test invalid profile
162+
with pytest.raises(ValueError) as e:
163+
validator.validate_profile("xccdf_com.example.www_profile_INVALID")
164+
assert "Profile ID 'xccdf_com.example.www_profile_INVALID' does not exist" in str(e.value)
165+
166+
# Test invalid value with suggestion
167+
with pytest.raises(ValueError) as e:
168+
validator.validate_value("xccdf_com.example.www_value_V3")
169+
assert "Value ID 'xccdf_com.example.www_value_V3' does not exist" in str(e.value)
170+
171+
# Test invalid rule with suggestion
172+
with pytest.raises(ValueError) as e:
173+
validator.validate_rule("xccdf_com.example.www_rule_R5")
174+
assert "Rule ID 'xccdf_com.example.www_rule_R5' does not exist" in str(e.value)
175+
176+
# Test invalid group
177+
with pytest.raises(ValueError) as e:
178+
validator.validate_group("xccdf_com.example.www_group_INVALID")
179+
assert "Group ID 'xccdf_com.example.www_group_INVALID' does not exist" in str(e.value)
180+
181+
182+
def test_profile_with_validator():
183+
"""Test that Profile uses validator to check IDs."""
184+
ds_path = pathlib.Path(__file__).parent.joinpath("data_stream.xml")
185+
validator = autotailor.DataStreamValidator(str(ds_path))
186+
187+
p = autotailor.Profile(validator=validator)
188+
p.reverse_dns = "com.example.www"
189+
190+
# Test valid variable change works
191+
p.add_value_change("V1", "30")
192+
193+
# Test invalid variable name fails
194+
with pytest.raises(ValueError) as e:
195+
p.add_value_change("INVALID_VAR", "test")
196+
assert "Value ID 'xccdf_com.example.www_value_INVALID_VAR' does not exist" in str(e.value)
197+
198+
# Test valid rule selection works
199+
p.select_rule("R1")
200+
201+
# Test invalid rule selection fails
202+
with pytest.raises(ValueError) as e:
203+
p.select_rule("INVALID_RULE")
204+
assert "Rule ID 'xccdf_com.example.www_rule_INVALID_RULE' does not exist" in str(e.value)
205+
206+
# Test valid base profile validation
207+
p.validate_base_profile("P1")
208+
209+
# Test invalid base profile fails
210+
with pytest.raises(ValueError) as e:
211+
p.validate_base_profile("INVALID_PROFILE")
212+
assert "Profile ID 'xccdf_com.example.www_profile_INVALID_PROFILE' does not exist" in str(e.value)
213+
214+
215+
def test_validator_suggestions():
216+
"""Test that validator provides helpful suggestions for typos."""
217+
ds_path = pathlib.Path(__file__).parent.joinpath("data_stream.xml")
218+
validator = autotailor.DataStreamValidator(str(ds_path))
219+
220+
# Test suggestion for value with typo (V11 instead of V1)
221+
with pytest.raises(ValueError) as e:
222+
validator.validate_value("xccdf_com.example.www_value_V11")
223+
error_msg = str(e.value)
224+
assert "Did you mean one of these?" in error_msg
225+
assert "xccdf_com.example.www_value_V1" in error_msg
226+
227+
# Test suggestion for rule with typo (R11 instead of R1)
228+
with pytest.raises(ValueError) as e:
229+
validator.validate_rule("xccdf_com.example.www_rule_R11")
230+
error_msg = str(e.value)
231+
assert "Did you mean one of these?" in error_msg
232+
assert "xccdf_com.example.www_rule_R1" in error_msg
233+
234+
235+
def test_validate_selector():
236+
"""Test that validate_selector rejects selectors not present in the data stream."""
237+
ds_path = pathlib.Path(__file__).parent.joinpath("data_stream.xml")
238+
validator = autotailor.DataStreamValidator(str(ds_path))
239+
240+
# V1 has selector "thirty"; V2 has "some" and "other"
241+
validator.validate_selector("xccdf_com.example.www_value_V1", "thirty")
242+
validator.validate_selector("xccdf_com.example.www_value_V2", "some")
243+
validator.validate_selector("xccdf_com.example.www_value_V2", "other")
244+
245+
# Invalid selector for V1
246+
with pytest.raises(ValueError) as e:
247+
validator.validate_selector("xccdf_com.example.www_value_V1", "invalid")
248+
error_msg = str(e.value)
249+
assert "Selector 'invalid' does not exist for Value 'xccdf_com.example.www_value_V1'" in error_msg
250+
assert "thirty" in error_msg
251+
252+
# Invalid selector for V2 with a close-enough typo triggers a suggestion
253+
with pytest.raises(ValueError) as e:
254+
validator.validate_selector("xccdf_com.example.www_value_V2", "ther")
255+
error_msg = str(e.value)
256+
assert "Selector 'ther' does not exist for Value 'xccdf_com.example.www_value_V2'" in error_msg
257+
assert "other" in error_msg
258+
259+
260+
def test_profile_selector_validation():
261+
"""Test that Profile validates selectors via -V/--var-select through refine_value."""
262+
ds_path = pathlib.Path(__file__).parent.joinpath("data_stream.xml")
263+
validator = autotailor.DataStreamValidator(str(ds_path))
264+
265+
p = autotailor.Profile(validator=validator)
266+
p.reverse_dns = "com.example.www"
267+
268+
# Valid selector passes
269+
p.change_selectors(["V1=thirty"])
270+
p.change_selectors(["V2=some"])
271+
272+
# Invalid selector raises
273+
with pytest.raises(ValueError) as e:
274+
p.change_selectors(["V1=invalid"])
275+
assert "Selector 'invalid' does not exist for Value 'xccdf_com.example.www_value_V1'" in str(e.value)
276+
277+
# Invalid value ID still raises before reaching selector check
278+
with pytest.raises(ValueError) as e:
279+
p.change_selectors(["NONEXISTENT=thirty"])
280+
assert "Value ID 'xccdf_com.example.www_value_NONEXISTENT' does not exist" in str(e.value)

0 commit comments

Comments
 (0)