debian-forge/test/mod/test_buildroot.py
Christian Kellner e0b7361b26 test/buildroot: check selinuxfs is read-only
This is a crucial pre-condition for the org.osbuild.selinux stage
to work properly, especially that it can set labels that are not
present in the policy on the host. If /sys/fs/selinux is writable,
setfiles will try to verify the labels via /sys/fs/selinux/context
and fail for unknown labels.
2020-08-12 16:52:27 +02:00

110 lines
3.4 KiB
Python

#
# Test for the build root
#
import pathlib
import os
import sys
import tempfile
import unittest
import osbuild
from osbuild.buildroot import BuildRoot
from osbuild.monitor import NullMonitor
from .. import test
@unittest.skipUnless(test.TestBase.can_bind_mount(), "root-only")
class TestBuildRoot(test.TestBase):
"""Check BuildRoot"""
def setUp(self):
self.tmp = tempfile.TemporaryDirectory()
def tearDown(self):
self.tmp.cleanup()
def test_basic(self):
# This also checks the API and BuildRoot integration:
# the runner will call api.setup_stdio and thus check
# that connecting to the api works correctly
runner = "org.osbuild.linux"
libdir = os.path.abspath(os.curdir)
var = pathlib.Path(self.tmp.name, "var")
var.mkdir()
monitor = NullMonitor(sys.stderr.fileno())
with BuildRoot("/", runner, libdir=libdir, var=var) as root:
api = osbuild.api.API({}, monitor)
root.register_api(api)
r = root.run(["/usr/bin/true"])
self.assertEqual(r.returncode, 0)
# Test we can use `.run` multiple times
r = root.run(["/usr/bin/true"])
self.assertEqual(r.returncode, 0)
r = root.run(["/usr/bin/false"])
self.assertNotEqual(r.returncode, 0)
@unittest.skipUnless(test.TestBase.have_test_data(), "no test-data access")
def test_bind_mounts(self):
runner = "org.osbuild.linux"
libdir = os.path.abspath(os.curdir)
var = pathlib.Path(self.tmp.name, "var")
var.mkdir()
rw_data = pathlib.Path(self.tmp.name, "data")
rw_data.mkdir()
scripts = os.path.join(self.locate_test_data(), "scripts")
monitor = NullMonitor(sys.stderr.fileno())
with BuildRoot("/", runner, libdir=libdir, var=var) as root:
api = osbuild.api.API({}, monitor)
root.register_api(api)
ro_binds = [f"{scripts}:/scripts"]
cmd = ["/scripts/mount_flags.py",
"/scripts",
"ro"]
r = root.run(cmd, readonly_binds=ro_binds)
self.assertEqual(r.returncode, 0)
cmd = ["/scripts/mount_flags.py",
"/rw-data",
"ro"]
binds = [f"{rw_data}:/rw-data"]
r = root.run(cmd, binds=binds, readonly_binds=ro_binds)
self.assertEqual(r.returncode, 1)
@unittest.skipUnless(test.TestBase.have_test_data(), "no test-data access")
@unittest.skipUnless(os.path.exists("/sys/fs/selinux"), "no SELinux")
def test_selinuxfs_ro(self):
# /sys/fs/selinux must never be writable in the container
# because RPM and other tools must not assume the policy
# of the host is the valid policy
runner = "org.osbuild.linux"
libdir = os.path.abspath(os.curdir)
var = pathlib.Path(self.tmp.name, "var")
var.mkdir()
scripts = os.path.join(self.locate_test_data(), "scripts")
monitor = NullMonitor(sys.stderr.fileno())
with BuildRoot("/", runner, libdir=libdir, var=var) as root:
api = osbuild.api.API({}, monitor)
root.register_api(api)
ro_binds = [f"{scripts}:/scripts"]
cmd = ["/scripts/mount_flags.py",
"/sys/fs/selinux",
"ro"]
r = root.run(cmd, readonly_binds=ro_binds)
self.assertEqual(r.returncode, 0)