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.
This commit is contained in:
Dusty Mabe 2024-09-17 12:22:16 -04:00 committed by Simon de Vlieger
parent ca1a21b923
commit f01a3d3c01
3 changed files with 30 additions and 12 deletions

View file

@ -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():

View file

@ -20,8 +20,17 @@
"schema_2": {
"options": {
"additionalProperties": false,
"required": [
"file_contexts"
"anyOf": [
{
"required": [
"file_contexts"
]
},
{
"required": [
"labels"
]
}
],
"properties": {
"file_contexts": {

View file

@ -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")