AkurAI Build
Menu

BifrOSt

public

Latest change 36972df1d1a942fadabbe03341629b5238357c8a - Reject unprepared installer bootstrap packages by Ólafur Búi Ólafsson

from __future__ import annotations

import copy
import importlib.machinery
import importlib.util
import json
from pathlib import Path
import sys
import tempfile
import unittest

ROOT = Path(__file__).resolve().parents[1]
TMP_ROOT = ROOT / ".tmp"


def load_python(name: str, path: Path):
    loader = importlib.machinery.SourceFileLoader(name, str(path))
    spec = importlib.util.spec_from_loader(name, loader)
    assert spec is not None
    module = importlib.util.module_from_spec(spec)
    sys.modules[name] = module
    loader.exec_module(module)
    return module


bootstrap = load_python(
    "bifrost_bootstrap",
    ROOT / "profile/airootfs/usr/local/lib/bifrost_bootstrap.py",
)
builder = load_python(
    "bifrost_alpm_builder",
    ROOT / "packaging/alpm/build-repository.py",
)

VERSION = "0.2.2"
REVISION = "a" * 40
EPOCH = 1_786_113_295


def prepared_release() -> dict[str, object]:
    return {
        "schema_version": 1,
        "provenance_status": "build-input",
        "version": VERSION,
        "source_revision": REVISION,
        "source_date_epoch": EPOCH,
        "build_id": f"bifrost-{VERSION}-{REVISION[:12]}-{EPOCH}",
        "profile_sha256": "b" * 64,
        "profile_digest_excludes": list(bootstrap.PROFILE_DIGEST_EXCLUDES),
        "iso": {
            "file": f"bifrost-{VERSION}-x86_64.iso",
            "bytes": None,
            "sha256": None,
        },
    }


class ReleaseDocumentTests(unittest.TestCase):
    def test_prepared_build_input_is_accepted(self) -> None:
        bootstrap.validate_release_document(prepared_release(), VERSION)

    def test_unsigned_development_payload_is_rejected(self) -> None:
        release = prepared_release()
        release.update(
            {
                "provenance_status": "unsigned-development",
                "source_revision": None,
                "source_date_epoch": 0,
                "build_id": None,
                "profile_sha256": None,
            }
        )
        with self.assertRaisesRegex(bootstrap.VerificationError, "not a prepared build input"):
            bootstrap.validate_release_document(release, VERSION)

    def test_mismatched_prepared_fields_are_rejected(self) -> None:
        cases = {
            "version": "0.2.1",
            "source_revision": "a" * 39,
            "source_date_epoch": True,
            "build_id": "wrong",
            "profile_sha256": "b" * 63,
            "profile_digest_excludes": [],
            "iso": {"file": "wrong.iso", "bytes": None, "sha256": None},
        }
        for field, value in cases.items():
            with self.subTest(field=field):
                release = copy.deepcopy(prepared_release())
                release[field] = value
                with self.assertRaises(bootstrap.VerificationError):
                    bootstrap.validate_release_document(release, VERSION)


class RepositoryBuildGateTests(unittest.TestCase):
    def setUp(self) -> None:
        TMP_ROOT.mkdir(exist_ok=True)
        self.directory = tempfile.TemporaryDirectory(dir=TMP_ROOT)
        self.addCleanup(self.directory.cleanup)
        self.root = Path(self.directory.name)
        self.release_path = (
            self.root
            / "profile/airootfs/usr/share/bifrost/installed-root/usr/share/bifrost/release.json"
        )
        self.release_path.parent.mkdir(parents=True)

    def write_release(self, release: dict[str, object]) -> None:
        self.release_path.write_text(json.dumps(release) + "\n", encoding="utf-8")

    def test_builder_accepts_prepared_provenance(self) -> None:
        self.write_release(prepared_release())
        builder.validate_source_provenance(self.root, VERSION)

    def test_builder_refuses_to_sign_unsigned_development_payload(self) -> None:
        release = prepared_release()
        release["provenance_status"] = "unsigned-development"
        self.write_release(release)
        with self.assertRaisesRegex(builder.BuildError, "run generate-release-metadata.py"):
            builder.validate_source_provenance(self.root, VERSION)


if __name__ == "__main__":
    unittest.main()