79 lines
2.9 KiB
Python
79 lines
2.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Disposable regression for the ISO rootfs archive's traversable root."""
|
|
|
|
from pathlib import Path
|
|
import os
|
|
import subprocess
|
|
import tempfile
|
|
import unittest
|
|
|
|
|
|
BUILDER = Path(__file__).resolve().parents[2] / "image-recipe/_archived/build-auto-installer-iso.sh"
|
|
|
|
|
|
def archive_root(root: Path, archive: Path) -> None:
|
|
subprocess.run(
|
|
["tar", "--numeric-owner", "-cf", str(archive), "-C", str(root), "."],
|
|
check=True,
|
|
)
|
|
|
|
|
|
def root_mode(archive: Path) -> str:
|
|
listing = subprocess.run(
|
|
["tar", "-tvf", str(archive), "."],
|
|
check=True, capture_output=True, text=True,
|
|
).stdout
|
|
return listing.splitlines()[0].split()[0]
|
|
|
|
|
|
def production_guard(source: str) -> str:
|
|
start = source.index('if [ "$(tar --occurrence=1 -tvf "$ROOTFS_TAR" . | awk')
|
|
end = source.index("\nfi", start) + len("\nfi")
|
|
return source[start:end]
|
|
|
|
|
|
class IsoRootModeTest(unittest.TestCase):
|
|
def test_old_archive_is_rejected_and_corrected_archive_passes(self) -> None:
|
|
source = BUILDER.read_text()
|
|
guard = production_guard(source)
|
|
with tempfile.TemporaryDirectory() as scratch:
|
|
root = Path(scratch) / "root"
|
|
root.mkdir(mode=0o700)
|
|
archive = Path(scratch) / "rootfs.tar"
|
|
archive_root(root, archive)
|
|
self.assertEqual(root_mode(archive), "drwx------")
|
|
invalid = subprocess.run(
|
|
["bash", "-eu", "-c", guard],
|
|
env={**os.environ, "ROOTFS_TAR": str(archive)},
|
|
capture_output=True, text=True,
|
|
)
|
|
self.assertNotEqual(invalid.returncode, 0)
|
|
self.assertIn("must be mode 0755", invalid.stderr)
|
|
|
|
root.chmod(0o755)
|
|
archive_root(root, archive)
|
|
self.assertEqual(root_mode(archive), "drwxr-xr-x")
|
|
valid = subprocess.run(
|
|
["bash", "-eu", "-c", guard],
|
|
env={**os.environ, "ROOTFS_TAR": str(archive)},
|
|
capture_output=True, text=True,
|
|
)
|
|
self.assertEqual(valid.returncode, 0, valid.stderr)
|
|
|
|
def test_guard_covers_cached_archive_and_installed_root(self) -> None:
|
|
source = BUILDER.read_text()
|
|
guard = production_guard(source)
|
|
self.assertLess(source.index("Using cached root filesystem"), source.index(guard))
|
|
self.assertLess(source.index(guard), source.index('if [ -n "$UAT_KERNEL" ]', source.index(guard)))
|
|
self.assertLess(source.index('run tar -xf "$ROOTFS_TAR" -C /mnt/target'),
|
|
source.index('run chmod 755 /mnt/target'))
|
|
self.assertLess(source.index('run chmod 755 /mnt/target'),
|
|
source.index('step "Encrypting data partition"'))
|
|
|
|
def test_builder_shell_syntax(self) -> None:
|
|
subprocess.run(["bash", "-n", str(BUILDER)], check=True)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|