Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions tests/utils/autotailor_integration_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,21 @@
python3 $autotailor --id-namespace "com.example.www" --json-tailoring $json_tailoring --tailored-profile-id=CMDL_P --select R3 $ds $original_profile > $tailoring
$OSCAP xccdf eval --profile CMDL_P --progress --tailoring-file $tailoring --results $result $ds
assert_exists 1 '/Benchmark/TestResult/rule-result[@idref="xccdf_com.example.www_rule_R3"]/result[text()="pass"]'

# test --local-path option with absolute path (should use basename)
python3 $autotailor --id-namespace "com.example.www" --local-path --select R3 $ds $original_profile > $tailoring
saved_result=$result
result=$tailoring
assert_exists 1 '/*[local-name()="Tailoring"]/*[local-name()="benchmark"][@href="data_stream.xml"]'
result=$saved_result
$OSCAP xccdf eval --profile P1_customized --progress --tailoring-file $tailoring --results $result $ds
assert_exists 1 '/Benchmark/TestResult/rule-result[@idref="xccdf_com.example.www_rule_R3"]/result[text()="pass"]'

# test default behavior (should use file:// URI)
python3 $autotailor --id-namespace "com.example.www" --select R3 $ds $original_profile > $tailoring

Check warning on line 152 in tests/utils/autotailor_integration_test.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of using the literal 'com.example.www' 16 times.

See more on https://sonarcloud.io/project/issues?id=OpenSCAP_openscap&issues=AZ2HHFVVrkWQeAovxF78&open=AZ2HHFVVrkWQeAovxF78&pullRequest=2337
saved_result=$result
result=$tailoring
assert_exists 1 '/*[local-name()="Tailoring"]/*[local-name()="benchmark"][starts-with(@href, "file://")]'
result=$saved_result
$OSCAP xccdf eval --profile P1_customized --progress --tailoring-file $tailoring --results $result $ds
assert_exists 1 '/Benchmark/TestResult/rule-result[@idref="xccdf_com.example.www_rule_R3"]/result[text()="pass"]'
26 changes: 26 additions & 0 deletions tests/utils/test_autotailor.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,29 @@ def test_no_id():
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"

def test_get_datastream_uri():
t = autotailor.Tailoring()

# Test default behavior with absolute path (file:// URI)
t.original_ds_filename = "/nonexistent/path/test-ds.xml"
t.use_local_path = False
uri = t._get_datastream_uri()
assert uri.startswith("file://")
assert uri.endswith("/nonexistent/path/test-ds.xml")

# Test local path mode with absolute path (basename only)
t.use_local_path = True
uri = t._get_datastream_uri()
assert uri == "test-ds.xml"

# Test local path mode with relative path (preserved as-is)
t.original_ds_filename = "relative/path/to/ds.xml"
uri = t._get_datastream_uri()
assert uri == "relative/path/to/ds.xml"

# Test default behavior with relative path (file:// URI)
t.use_local_path = False
uri = t._get_datastream_uri()
assert uri.startswith("file://")
assert "relative/path/to/ds.xml" in uri
29 changes: 27 additions & 2 deletions utils/autotailor
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ class Tailoring:
self.id = "xccdf_auto_tailoring_default"
self.version = 1
self.original_ds_filename = ""
self.use_local_path = False

self.profiles = []

Expand All @@ -318,12 +319,31 @@ class Tailoring:
self.profiles.append(profile)
return profile

def _get_datastream_uri(self):
"""
Determine the datastream URI based on the use_local_path setting.

Returns:
str: The URI/path to use in the benchmark href attribute
"""
if self.use_local_path:
# Preserve relative paths as-is, convert absolute paths to basename
ds_path = pathlib.Path(self.original_ds_filename)
if ds_path.is_absolute():
# Convert absolute path to basename for compatibility with layered products
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The option name is -relative-path but if this branch is executed there will be a basename which doesn't have to be a relative path. Consider some better name for the command line option.

return ds_path.name
else:
# Keep relative paths as provided by the user
return self.original_ds_filename
else:
# Use absolute URI (default behavior for backward compatibility)
return pathlib.Path(self.original_ds_filename).absolute().as_uri()

def to_xml(self, root):
root.set("id", self.id)

benchmark = ET.SubElement(root, "{%s}benchmark" % NS)
datastream_uri = pathlib.Path(
self.original_ds_filename).absolute().as_uri()
datastream_uri = self._get_datastream_uri()
benchmark.set("href", datastream_uri)

version = ET.SubElement(root, "{%s}version" % NS)
Expand Down Expand Up @@ -436,6 +456,10 @@ def get_parser():
"-o", "--output", default="-",
help="Where to save the tailoring file. If not supplied, write to "
"standard output.")
parser.add_argument(
"--local-path", action="store_true",
help="Use local path for the benchmark href instead of absolute file:// URI. "
"Absolute paths are converted to basename, relative paths are preserved.")
return parser


Expand All @@ -452,6 +476,7 @@ if __name__ == "__main__":
t = Tailoring()
t.original_ds_filename = args.datastream
t.reverse_dns = args.id_namespace
t.use_local_path = args.local_path

if args.json_tailoring:
t.import_json_tailoring(args.json_tailoring)
Expand Down
7 changes: 7 additions & 0 deletions utils/autotailor.8
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,13 @@ Import tailoring from a JSON file (https://github.com/ComplianceAsCode/schemas/t
However, data passed in the command line options takes precedence over JSON contents, including the BASE_PROFILE_ID argument.
JSON tailoring can be accompanied with additional command-line options to either override contents of an existing profile (along with --tailored-profile-id identifier) or to create an extra profile (BASE_PROFILE_ID is a mandatory argument in this case and --tailored-profile-id is optional) in the resulting XCCDF tailoring file.
.RE
.TP
\fB--local-path\fR
.RS
Use local path for the benchmark href instead of absolute file:// URI. This option is useful for compatibility with layered products like Red Hat Satellite that cannot resolve local filesystem paths.
When this option is specified, absolute paths are converted to basename only, while relative paths are preserved as provided.
By default, the tool uses absolute file:// URIs for backward compatibility.
.RE

.SH USAGE
.SS Modify a variable value
Expand Down
Loading