stages: add org.osbuild.ostree.selinux

Fix SELinux labels for an OSTree deployment.
This commit is contained in:
Christian Kellner 2021-06-06 14:53:56 +00:00
parent 467f313cee
commit 3d197247b2

View file

@ -0,0 +1,95 @@
#!/usr/bin/python3
"""
Fix SELinux labels for an OSTree deployment[1].
[1] https://ostree.readthedocs.io/en/latest/manual/deployment/
"""
import os
import sys
import osbuild.api
from osbuild.util import ostree
from osbuild.util import selinux
SCHEMA = """
"additionalProperties": false,
"required": ["deployment"],
"properties": {
"deployment": {
"additionalProperties": false,
"required": ["osname", "ref"],
"properties": {
"osname": {
"description": "Name of the stateroot to be used in the deployment",
"type": "string"
},
"ref": {
"description": "OStree ref to create and use for deployment",
"type": "string"
},
"serial": {
"description": "The deployment serial (usually '0')",
"type": "number",
"default": 0
}
}
}
}
"""
def main(tree, options):
dep = options["deployment"]
osname = dep["osname"]
ref = dep["ref"]
serial = dep.get("serial", 0)
# this created a state root at `osname`
stateroot = f"{tree}/ostree/deploy/{osname}"
root = ostree.deployment_path(tree, osname, ref, serial)
# deploying a tree creates new files that need to be properly
# labeled for SELinux. In theory, ostree will take care of
# this by loading the SELinux config from the deployment and
# then applying the labels; but it does so conditionally on
# is_selinux_enabled(2), which in our container is FALSE
# Therefore we have to do the same dance as ostree does, at
# least for now, and manually re-label the affected paths
se_policy = None
for p in ["etc/selinux", "usr/etc/selinux"]:
se_home = os.path.join(root, p)
cfgfile = os.path.join(se_home, "config")
if not os.path.isfile(cfgfile):
continue
with open(cfgfile, 'r') as f:
cfg = selinux.parse_config(f)
se_policy = selinux.config_get_policy(cfg)
if se_policy:
break
if not se_policy:
raise ValueError("Could not find SELinux policy")
spec = f"{se_home}/{se_policy}/contexts/files/file_contexts"
# kernel, initramfs & BLS config snippets were
# written to {tree}/boot
selinux.setfiles(spec, tree, "/boot")
# various config files will be created as a result
# of the 3-way configuration merge, see ostree(3)
selinux.setfiles(spec, root, "/etc")
# if we populated /var, we need to fix its labels
selinux.setfiles(spec, stateroot, "/var")
if __name__ == '__main__':
stage_args = osbuild.api.arguments()
r = main(stage_args["tree"],
stage_args["options"])
sys.exit(r)