From f01a3d3c01f5c3e86b0ca51a3f90fbde38c3b769 Mon Sep 17 00:00:00 2001 From: Dusty Mabe Date: Tue, 17 Sep 2024 12:22:16 -0400 Subject: [PATCH] stages/selinux: don't require file_contexts if labels passed With the labels option the user is specifying the exact context they want to set on the path so it's not necessary to supply a context here. This can be also useful in the case where you want to set some labels and you haven't yet populated the tree yet. --- stages/org.osbuild.selinux | 11 +++++++---- stages/org.osbuild.selinux.meta.json | 13 +++++++++++-- stages/test/test_selinux.py | 18 ++++++++++++------ 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/stages/org.osbuild.selinux b/stages/org.osbuild.selinux index bb45298d..563d827b 100755 --- a/stages/org.osbuild.selinux +++ b/stages/org.osbuild.selinux @@ -8,11 +8,14 @@ from osbuild.util import selinux def main(tree, options): - file_contexts = os.path.join(f"{tree}", options["file_contexts"]) + file_contexts = options.get("file_contexts") exclude_paths = options.get("exclude_paths") - if exclude_paths: - exclude_paths = [os.path.join(tree, p.lstrip("/")) for p in exclude_paths] - selinux.setfiles(file_contexts, os.fspath(tree), "", exclude_paths=exclude_paths) + + if file_contexts: + file_contexts = os.path.join(f"{tree}", options["file_contexts"]) + if exclude_paths: + exclude_paths = [os.path.join(tree, p.lstrip("/")) for p in exclude_paths] + selinux.setfiles(file_contexts, os.fspath(tree), "", exclude_paths=exclude_paths) labels = options.get("labels", {}) for path, label in labels.items(): diff --git a/stages/org.osbuild.selinux.meta.json b/stages/org.osbuild.selinux.meta.json index ea1bb3ef..30dbddae 100644 --- a/stages/org.osbuild.selinux.meta.json +++ b/stages/org.osbuild.selinux.meta.json @@ -20,8 +20,17 @@ "schema_2": { "options": { "additionalProperties": false, - "required": [ - "file_contexts" + "anyOf": [ + { + "required": [ + "file_contexts" + ] + }, + { + "required": [ + "labels" + ] + } ], "properties": { "file_contexts": { diff --git a/stages/test/test_selinux.py b/stages/test/test_selinux.py index af1e1b56..7cb51bcd 100644 --- a/stages/test/test_selinux.py +++ b/stages/test/test_selinux.py @@ -10,13 +10,15 @@ from osbuild import testutil STAGE_NAME = "org.osbuild.selinux" -def get_test_input(test_data, implicit_file_contexts=True): +def get_test_input(test_data, file_contexts=False, labels=False): test_input = { "type": STAGE_NAME, "options": {} } - if implicit_file_contexts: + if file_contexts: test_input["options"]["file_contexts"] = "some-context" + if labels: + test_input["options"]["labels"] = {"/path/to/file": "label_to_apply"} test_input["options"].update(test_data) return test_input @@ -33,7 +35,7 @@ def get_test_input(test_data, implicit_file_contexts=True): ({"force_autorelabel": "foo"}, "'foo' is not of type 'boolean'"), ]) def test_schema_validation_selinux(stage_schema, test_data, expected_err): - res = stage_schema.validate(get_test_input(test_data)) + res = stage_schema.validate(get_test_input(test_data, file_contexts=True, labels=False)) if expected_err == "": assert res.valid is True, f"err: {[e.as_dict() for e in res.errors]}" else: @@ -41,11 +43,15 @@ def test_schema_validation_selinux(stage_schema, test_data, expected_err): testutil.assert_jsonschema_error_contains(res, expected_err, expected_num_errs=1) -def test_schema_validation_selinux_file_context_required(stage_schema): - res = stage_schema.validate(get_test_input({}, implicit_file_contexts=False)) +def test_schema_validation_selinux_required_options(stage_schema): + res = stage_schema.validate(get_test_input({}, file_contexts=False, labels=False)) assert res.valid is False - expected_err = "'file_contexts' is a required property" + expected_err = "{} is not valid under any of the given schemas" testutil.assert_jsonschema_error_contains(res, expected_err, expected_num_errs=1) + res = stage_schema.validate(get_test_input({}, file_contexts=True, labels=False)) + assert res.valid is True + res = stage_schema.validate(get_test_input({}, file_contexts=False, labels=True)) + assert res.valid is True @patch("osbuild.util.selinux.setfiles")