org.osbuild.selinux: support for specifying where file_contexts comes from
file_context now can come from
- tree (current default)
- mount
- input
Example:
```
- type: org.osbuild.selinux
inputs:
tree:
type: org.osbuild.tree
origin: org.osbuild.pipeline
references:
- name:tree
options:
file_contexts: input://tree/etc/selinux/targeted/contexts/files/file_contexts
```
This commit is contained in:
parent
84d4de5770
commit
a8e8ebde44
3 changed files with 56 additions and 24 deletions
|
|
@ -9,6 +9,7 @@ from osbuild.util import parsing, selinux
|
|||
|
||||
def main(args):
|
||||
# Get the path where the tree is
|
||||
tree = args["tree"]
|
||||
options = args["options"]
|
||||
file_contexts = options.get("file_contexts")
|
||||
exclude_paths = options.get("exclude_paths")
|
||||
|
|
@ -16,7 +17,10 @@ def main(args):
|
|||
root, target = parsing.parse_location_into_parts(target, args)
|
||||
|
||||
if file_contexts:
|
||||
file_contexts = os.path.join(args["tree"], options["file_contexts"])
|
||||
if "://" not in file_contexts:
|
||||
file_contexts = os.path.normpath(f"{tree}/{file_contexts}")
|
||||
else:
|
||||
file_contexts = parsing.parse_location(file_contexts, args)
|
||||
if exclude_paths:
|
||||
exclude_paths = [os.path.normpath(f"{root}/{target}/{p}") for p in exclude_paths]
|
||||
selinux.setfiles(file_contexts, os.path.normpath(root), target, exclude_paths=exclude_paths)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"summary": "Set SELinux file contexts",
|
||||
"description": [
|
||||
"Sets correct SELinux labels for every file in the tree, according to the",
|
||||
"SELinux policy installed inside the tree.",
|
||||
"Sets correct SELinux labels for every file in the tree or on mount, according to",
|
||||
"the SELinux policy.",
|
||||
"Uses the host's `setfiles` program and the tree's `file_contexts`, usually",
|
||||
" /etc/selinux/<SELINUXTYPE>/contexts/files/file_contexts",
|
||||
"where <SELINUXTYPE> is the value set in /etc/selinux/config (usually \"targeted\"",
|
||||
|
|
@ -40,8 +40,8 @@
|
|||
"default": "tree:///"
|
||||
},
|
||||
"file_contexts": {
|
||||
"type": "string",
|
||||
"description": "Path to the active SELinux policy's `file_contexts`"
|
||||
"description": "Path to the active SELinux policy's `file_contexts`. Supports `tree://`, `mount://`, and `input://` schemes. Plain paths imply `tree://`.",
|
||||
"type": "string"
|
||||
},
|
||||
"exclude_paths": {
|
||||
"type": "array",
|
||||
|
|
@ -70,6 +70,10 @@
|
|||
},
|
||||
"mounts": {
|
||||
"type": "array"
|
||||
},
|
||||
"inputs": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ def get_test_input(test_data, file_contexts=False, labels=False):
|
|||
({"exclude_paths": ["/sysroot"]}, ""),
|
||||
({"target": "mount://disk/boot/efi"}, ""),
|
||||
({"target": "tree:///boot/efi"}, ""),
|
||||
({"file_contexts": "path/to/file_contexts"}, ""),
|
||||
# bad
|
||||
({"target": "/boot/efi"}, "'/boot/efi' does not match '^mount://[^/]+/|^tree:///'"),
|
||||
({"file_contexts": 1234}, "1234 is not of type 'string'"),
|
||||
|
|
@ -58,19 +59,38 @@ def test_schema_validation_selinux_required_options(stage_schema):
|
|||
|
||||
|
||||
@patch("osbuild.util.selinux.setfiles")
|
||||
def test_selinux_file_contexts(mocked_setfiles, tmp_path, stage_module):
|
||||
options = {
|
||||
def test_selinux_file_contexts_schemeless_relpath(mocked_setfiles, tmp_path, stage_module):
|
||||
tree = tmp_path / "tree"
|
||||
|
||||
args = {
|
||||
"tree": tree,
|
||||
"options": {
|
||||
"file_contexts": "etc/selinux/thing",
|
||||
}
|
||||
args = {
|
||||
"tree": f"{tmp_path}",
|
||||
"options": options
|
||||
}
|
||||
stage_module.main(args)
|
||||
|
||||
assert len(mocked_setfiles.call_args_list) == 1
|
||||
args, kwargs = mocked_setfiles.call_args_list[0]
|
||||
assert args == (f"{tmp_path}/etc/selinux/thing", os.fspath(tmp_path), "/")
|
||||
assert args == (f"{tree}/etc/selinux/thing", os.fspath(tree), "/")
|
||||
assert kwargs == {"exclude_paths": None}
|
||||
|
||||
|
||||
@patch("osbuild.util.selinux.setfiles")
|
||||
def test_selinux_file_contexts_schemeless_abspath(mocked_setfiles, tmp_path, stage_module):
|
||||
tree = tmp_path / "tree"
|
||||
|
||||
args = {
|
||||
"tree": tree,
|
||||
"options": {
|
||||
"file_contexts": "/etc/selinux/thing",
|
||||
}
|
||||
}
|
||||
stage_module.main(args)
|
||||
|
||||
assert len(mocked_setfiles.call_args_list) == 1
|
||||
args, kwargs = mocked_setfiles.call_args_list[0]
|
||||
assert args == (f"{tree}/etc/selinux/thing", os.fspath(tree), "/")
|
||||
assert kwargs == {"exclude_paths": None}
|
||||
|
||||
|
||||
|
|
@ -78,44 +98,48 @@ def test_selinux_file_contexts(mocked_setfiles, tmp_path, stage_module):
|
|||
def test_selinux_file_contexts_mounts(mocked_setfiles, tmp_path, stage_module):
|
||||
tree = tmp_path / "tree"
|
||||
mounts = tmp_path / "mounts"
|
||||
root = mounts / "."
|
||||
|
||||
args = {
|
||||
"tree": f"{tree}",
|
||||
"tree": tree,
|
||||
"options": {
|
||||
"file_contexts": "etc/selinux/thing",
|
||||
"file_contexts": "mount://root/etc/selinux/file_contexts",
|
||||
"target": "mount://root/"
|
||||
},
|
||||
"paths": {
|
||||
"mounts": mounts,
|
||||
},
|
||||
"mounts": {
|
||||
"root": {"path": mounts}
|
||||
"root": {
|
||||
"path": root
|
||||
}
|
||||
}
|
||||
}
|
||||
stage_module.main(args)
|
||||
|
||||
assert len(mocked_setfiles.call_args_list) == 1
|
||||
args, kwargs = mocked_setfiles.call_args_list[0]
|
||||
assert args == (f"{tree}/etc/selinux/thing", f"{mounts}", "/")
|
||||
assert args == (f"{mounts}/etc/selinux/file_contexts", f"{mounts}", "/")
|
||||
assert kwargs == {"exclude_paths": None}
|
||||
|
||||
|
||||
@patch("osbuild.util.selinux.setfiles")
|
||||
def test_selinux_file_contexts_exclude(mocked_setfiles, tmp_path, stage_module):
|
||||
options = {
|
||||
tree = tmp_path / "tree"
|
||||
|
||||
args = {
|
||||
"tree": tree,
|
||||
"options": {
|
||||
"file_contexts": "etc/selinux/thing",
|
||||
"exclude_paths": ["/sysroot"],
|
||||
}
|
||||
args = {
|
||||
"tree": f"{tmp_path}",
|
||||
"options": options
|
||||
}
|
||||
stage_module.main(args)
|
||||
|
||||
assert len(mocked_setfiles.call_args_list) == 1
|
||||
args, kwargs = mocked_setfiles.call_args_list[0]
|
||||
assert args == (f"{tmp_path}/etc/selinux/thing", os.fspath(tmp_path), "/")
|
||||
assert kwargs == {"exclude_paths": [f"{tmp_path}/sysroot"]}
|
||||
assert args == (f"{tree}/etc/selinux/thing", os.fspath(tree), "/")
|
||||
assert kwargs == {"exclude_paths": [f"{tree}/sysroot"]}
|
||||
|
||||
|
||||
@patch("osbuild.util.selinux.setfilecon")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue