osbuild: add support to exclude_paths to setfiles()
This is needed because on a mounted `bootc` container `setfiles` without excluding `/sysroot` will create many warnings like: ``` setfiles: conflicting specifications for /run/osbuild/tree/sysroot/ostree/repo/objects/00/0ef9ada2ee87792e8ba21afd65aa00d79a1253018832652b8694862fb80e84.file and /run/osbuild/tree/usr/lib/firmware/cirrus/cs35l41-dsp1-spk-prot-103c8b8f-r1.bin.xz, using system_u:object_r:lib_t:s0. ``` but simply excluding this dir fixes them.
This commit is contained in:
parent
ba08a524a4
commit
0528ccc3f0
5 changed files with 52 additions and 6 deletions
|
|
@ -3,7 +3,7 @@
|
|||
import errno
|
||||
import os
|
||||
import subprocess
|
||||
from typing import Dict, TextIO
|
||||
from typing import Dict, List, Optional, TextIO
|
||||
|
||||
# Extended attribute name for SELinux labels
|
||||
XATTR_NAME_SELINUX = b"security.selinux"
|
||||
|
|
@ -35,7 +35,7 @@ def config_get_policy(config: Dict[str, str]):
|
|||
return config.get('SELINUXTYPE', None)
|
||||
|
||||
|
||||
def setfiles(spec_file: str, root: str, *paths):
|
||||
def setfiles(spec_file: str, root: str, *paths, exclude_paths: Optional[List[str]] = None) -> None:
|
||||
"""Initialize the security context fields for `paths`
|
||||
|
||||
Initialize the security context fields (extended attributes)
|
||||
|
|
@ -43,10 +43,18 @@ def setfiles(spec_file: str, root: str, *paths):
|
|||
`root` argument determines the root path of the file system
|
||||
and the entries in `path` are interpreted as relative to it.
|
||||
Uses the setfiles(8) tool to actually set the contexts.
|
||||
Paths can be excluded via the exclude_paths argument.
|
||||
"""
|
||||
if exclude_paths is None:
|
||||
exclude_paths = []
|
||||
exclude_paths_args = []
|
||||
for p in exclude_paths:
|
||||
exclude_paths_args.extend(["-e", p])
|
||||
|
||||
for path in paths:
|
||||
subprocess.run(["setfiles", "-F",
|
||||
"-r", root,
|
||||
*exclude_paths_args,
|
||||
spec_file,
|
||||
f"{root}{path}"],
|
||||
check=True)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,10 @@ from osbuild.util import selinux
|
|||
|
||||
def main(tree, options):
|
||||
file_contexts = os.path.join(f"{tree}", options["file_contexts"])
|
||||
selinux.setfiles(file_contexts, os.fspath(tree), "")
|
||||
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)
|
||||
|
||||
labels = options.get("labels", {})
|
||||
for path, label in labels.items():
|
||||
|
|
|
|||
|
|
@ -27,6 +27,13 @@
|
|||
"type": "string",
|
||||
"description": "Path to the active SELinux policy's `file_contexts`"
|
||||
},
|
||||
"exclude_paths": {
|
||||
"type": "array",
|
||||
"description": "Paths to exclude when setting labels via file_contexts",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"type": "object",
|
||||
"description": "Labels to set of the specified files or folders",
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ def get_test_input(test_data, implicit_file_contexts=True):
|
|||
# good
|
||||
({"labels": {"/usr/bin/cp": "system_u:object_r:install_exec_t:s0"}}, ""),
|
||||
({"force_autorelabel": True}, ""),
|
||||
({"exclude_paths": ["/sysroot"]}, ""),
|
||||
# bad
|
||||
({"file_contexts": 1234}, "1234 is not of type 'string'"),
|
||||
({"labels": "xxx"}, "'xxx' is not of type 'object'"),
|
||||
|
|
@ -57,9 +58,23 @@ def test_selinux_file_contexts(mocked_setfiles, tmp_path, stage_module):
|
|||
stage_module.main(tmp_path, options)
|
||||
|
||||
assert len(mocked_setfiles.call_args_list) == 1
|
||||
assert mocked_setfiles.call_args_list == [
|
||||
call(f"{tmp_path}/etc/selinux/thing", os.fspath(tmp_path), "")
|
||||
]
|
||||
args, kwargs = mocked_setfiles.call_args_list[0]
|
||||
assert args == (f"{tmp_path}/etc/selinux/thing", os.fspath(tmp_path), "")
|
||||
assert kwargs == {"exclude_paths": None}
|
||||
|
||||
|
||||
@patch("osbuild.util.selinux.setfiles")
|
||||
def test_selinux_file_contexts_exclude(mocked_setfiles, tmp_path, stage_module):
|
||||
options = {
|
||||
"file_contexts": "etc/selinux/thing",
|
||||
"exclude_paths": ["/sysroot"],
|
||||
}
|
||||
stage_module.main(tmp_path, options)
|
||||
|
||||
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"]}
|
||||
|
||||
|
||||
@patch("osbuild.util.selinux.setfilecon")
|
||||
|
|
|
|||
|
|
@ -74,3 +74,16 @@ def test_selinux_setfiles(mocked_run, tmp_path):
|
|||
["setfiles", "-F", "-r", os.fspath(tmp_path),
|
||||
"/etc/selinux/thing", os.fspath(tmp_path) + "/boot"], check=True),
|
||||
]
|
||||
|
||||
|
||||
@mock.patch("subprocess.run")
|
||||
def test_selinux_setfiles_exclude(mocked_run, tmp_path):
|
||||
selinux.setfiles("/etc/selinux/thing", os.fspath(tmp_path), "/", exclude_paths=["/sysroot", "/other/dir"])
|
||||
|
||||
assert len(mocked_run.call_args_list) == 1
|
||||
assert mocked_run.call_args_list == [
|
||||
mock.call(
|
||||
["setfiles", "-F", "-r", os.fspath(tmp_path),
|
||||
"-e", "/sysroot", "-e", "/other/dir",
|
||||
"/etc/selinux/thing", os.fspath(tmp_path) + "/"], check=True),
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue