From 5884209867ec6b55cd321569f86dcaaa1502dd3f Mon Sep 17 00:00:00 2001 From: Matthew Burket Date: Thu, 2 Apr 2026 07:33:21 -0500 Subject: [PATCH] Backport Allow for only id or base_profile_id in JSON Add tests for the changes Backport #2318 --- tests/utils/autotailor_integration_test.sh | 1 - tests/utils/custom_no_ids.json | 12 ++++++++++++ tests/utils/test_autotailor.py | 14 ++++++++++++++ utils/autotailor | 5 ++++- 4 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 tests/utils/custom_no_ids.json diff --git a/tests/utils/autotailor_integration_test.sh b/tests/utils/autotailor_integration_test.sh index e0681783e7..14b20cbcae 100755 --- a/tests/utils/autotailor_integration_test.sh +++ b/tests/utils/autotailor_integration_test.sh @@ -83,7 +83,6 @@ assert_exists 1 '/Benchmark/TestResult/rule-result[@idref="xccdf_com.example.www assert_exists 1 '/Benchmark/TestResult/rule-result[@idref="xccdf_com.example.www_rule_R4"]/result[text()="notchecked"]' assert_exists 1 '/Benchmark/TestResult/rule-result[@idref="xccdf_com.example.www_rule_R4" and @role="unchecked"]' - # select additional rule R3; the customized profile will have a special profile ID customized_profile="xccdf_com.pink.elephant_profile_pineapple" python3 $autotailor --new-profile-id $customized_profile --id-namespace "com.example.www" --select R3 $ds $original_profile > $tailoring diff --git a/tests/utils/custom_no_ids.json b/tests/utils/custom_no_ids.json new file mode 100644 index 0000000000..979478c73e --- /dev/null +++ b/tests/utils/custom_no_ids.json @@ -0,0 +1,12 @@ +{ + "profiles": [ + { + "title": "JSON Tailored Profile P11", + "rules": { + "R3": { + "evaluate": true + } + } + } + ] +} diff --git a/tests/utils/test_autotailor.py b/tests/utils/test_autotailor.py index 202d5b9281..ad72bbd4ab 100644 --- a/tests/utils/test_autotailor.py +++ b/tests/utils/test_autotailor.py @@ -1,4 +1,7 @@ import importlib +import pathlib +import json + import pytest NS = "http://checklists.nist.gov/xccdf/1.2" @@ -94,3 +97,14 @@ def test_refine_rule(): "'high'.") assert t.rule_refinements(fav, "severity") == "high" assert t.rule_refinements(fav, "role") == "full" + +def test_no_id(): + p = autotailor.Profile() + profile_dict = None + file_path = pathlib.Path(__file__).parent.joinpath("custom_no_ids.json") + with open(file_path) as fp: + json_data = json.load(fp) + profile_dict = json_data["profiles"][0] + with pytest.raises(ValueError) as e: + p.import_json_tailoring_profile(profile_dict) + assert str(e.value) == "You must define a base_profile_id or an id" diff --git a/utils/autotailor b/utils/autotailor index 4bd751dd37..97473e5dd5 100755 --- a/utils/autotailor +++ b/utils/autotailor @@ -254,6 +254,8 @@ class Tailoring: profile = ET.SubElement(root, "{%s}Profile" % NS) profile.set("id", self._full_profile_id(self.profile_id)) profile.set("extends", self._full_profile_id(self.extends)) + if self.extends: + profile.set("extends", self._full_profile_id(self.extends)) # Title has to be there due to the schema definition. title = ET.SubElement(profile, "{%s}title" % NS) @@ -315,7 +317,8 @@ class Tailoring: raise ValueError("JSON Tailoring does not define any profiles.") self.extends = tailoring["base_profile_id"] - + if not tailoring.get("base_profile_id") and not tailoring.get("id"): + raise ValueError("You must define a base_profile_id or an id") self.profile_id = tailoring.get("id", self.profile_id) self.profile_title = tailoring.get("title", self.profile_title)