47 lines
2.1 KiB
Python
47 lines
2.1 KiB
Python
"""Check packaged code readability and writable temporary test output as non-root."""
|
|
import os
|
|
from pathlib import Path
|
|
import tempfile
|
|
|
|
SOURCE_DIRS = ("netplan_v4", "tests", "integrations", "gui")
|
|
SOURCE_FILES = ("run_tests.py", "install_hooks.py", "runtime_preflight.py", "requirements.txt")
|
|
|
|
|
|
def verify_access(root, reports):
|
|
root, reports = Path(root).resolve(), Path(reports).resolve()
|
|
if reports == root or root in reports.parents:
|
|
raise ValueError("Test reports must be outside the packaged application tree")
|
|
if not root.is_dir() or not os.access(root, os.R_OK | os.X_OK):
|
|
raise PermissionError(f"Application directory is not accessible: {root}")
|
|
paths = [root / name for name in SOURCE_FILES]
|
|
for name in SOURCE_DIRS:
|
|
directory = root / name
|
|
if not directory.is_dir():
|
|
raise FileNotFoundError(f"Missing packaged directory: {directory}")
|
|
def on_error(error):
|
|
raise error
|
|
for parent, directories, files in os.walk(directory, onerror=on_error):
|
|
base = Path(parent)
|
|
if not os.access(base, os.R_OK | os.X_OK):
|
|
raise PermissionError(f"Packaged directory is not accessible: {base}")
|
|
if any((base / child).is_symlink() for child in directories + files):
|
|
raise ValueError(f"Unexpected symlink in packaged source: {base}")
|
|
paths.extend(base / name for name in files)
|
|
for path in paths:
|
|
with path.open("rb") as handle:
|
|
handle.read(1)
|
|
reports.mkdir(parents=True, exist_ok=True)
|
|
with tempfile.TemporaryFile(dir=reports) as probe:
|
|
probe.write(b"permission check")
|
|
probe.flush()
|
|
return len(paths)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
if os.geteuid() == 0:
|
|
raise SystemExit("Runtime preflight must run as the unprivileged container user")
|
|
reports = Path(os.getenv("NETPLAN_V4_TEST_REPORT_DIR", "/tmp/test-results"))
|
|
count = verify_access(Path(__file__).resolve().parent, reports)
|
|
import numpy, scipy, fastapi, httpx
|
|
print(f"Non-root runtime check OK: uid={os.geteuid()}, readable_files={count}, reports={reports}")
|