813 lines
36 KiB
Python
813 lines
36 KiB
Python
from __future__ import annotations
|
|
|
|
import hashlib
|
|
import importlib.util
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
from typing import Any, cast
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
PUBLISHER_PATH = ROOT / "scripts" / "publish_mcp_hub_ingestion.py"
|
|
FIXED_REPOSITORY = "jens/itworx_mcp_hub"
|
|
IMAGE_REPOSITORY = "gitea.example.com/jens/itworx-mcp-hub/connector-ingestion"
|
|
SOURCE_URI = "https://gitea.example.com/jens/itworx-mcp-hub"
|
|
REVISION = "a" * 40
|
|
TREE = "b" * 40
|
|
MANIFEST_DIGEST = "sha256:" + "c" * 64
|
|
CONFIG_DIGEST = "sha256:" + "d" * 64
|
|
BUILT_AT = "2026-10-03T01:02:03.004Z"
|
|
EPOCH = "1790980806"
|
|
ENGINE_ID = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
|
CONTAINER_ID = "f" * 64
|
|
_OMITTED = object()
|
|
|
|
|
|
def _load_publisher() -> Any:
|
|
spec = importlib.util.spec_from_file_location("test_publish_mcp_hub_ingestion", PUBLISHER_PATH)
|
|
if spec is None or spec.loader is None:
|
|
raise AssertionError("fixed ingestion publisher script could not be loaded")
|
|
module = importlib.util.module_from_spec(spec)
|
|
sys.modules[spec.name] = module
|
|
spec.loader.exec_module(module)
|
|
return module
|
|
|
|
|
|
class PublisherHarness:
|
|
def __init__(self) -> None:
|
|
self.temporary = tempfile.TemporaryDirectory()
|
|
self.root = Path(self.temporary.name)
|
|
self.volume_root = self.root / "volume"
|
|
self.releases_root = self.volume_root / "releases"
|
|
self.source = self.releases_root / REVISION
|
|
self.publisher = _load_publisher()
|
|
self.publisher.FIXED_VOLUME_ROOT = self.volume_root
|
|
self.publisher.FIXED_RELEASES_ROOT = self.releases_root
|
|
self.state_root = self.root / "state"
|
|
self.publisher.FIXED_STATE_ROOT = self.state_root
|
|
dockerfile = self.source / "infrastructure" / "images" / "python-service" / "Dockerfile"
|
|
dockerfile.parent.mkdir(parents=True)
|
|
dockerfile.write_text("FROM python:3.13-slim\n", encoding="utf-8")
|
|
self.script = self.source / "scripts" / "publish_mcp_hub_ingestion.py"
|
|
self.script.parent.mkdir(parents=True)
|
|
self.script.write_text("# frozen publisher\n", encoding="utf-8")
|
|
self.state_root.mkdir(mode=0o700)
|
|
self.freeze_build = {
|
|
"id": REVISION[:12],
|
|
"repository": FIXED_REPOSITORY,
|
|
"revision": REVISION,
|
|
"tree": TREE,
|
|
"treeDigest": hashlib.sha256(f"git-tree:{TREE}".encode()).hexdigest(),
|
|
"builtAt": BUILT_AT,
|
|
}
|
|
self.frozen = self.publisher.FrozenSource(
|
|
repository=FIXED_REPOSITORY,
|
|
revision=REVISION,
|
|
build=dict(self.freeze_build),
|
|
source_date_epoch=EPOCH,
|
|
freeze_sha256="e" * 64,
|
|
controller_source_path=f"/controller-hub-releases/releases/{REVISION}",
|
|
)
|
|
self.command_calls: list[list[str]] = []
|
|
self.builder_present = False
|
|
self.builder_bootstrapped = False
|
|
self.builder_container_present = False
|
|
self.bad_builder_image = False
|
|
self.bad_builder_container_image = False
|
|
self.bad_builder_actual_image = False
|
|
self.builder_runtime_overrides: dict[str, Any] = {}
|
|
self.bad_labels = False
|
|
self.bad_manifest = False
|
|
self.bad_config = False
|
|
self.redaction_sentinel = "sentinel-value-must-not-escape"
|
|
if os.name != "nt":
|
|
for path in sorted(
|
|
self.source.rglob("*"), key=lambda item: len(item.parts), reverse=True
|
|
):
|
|
if path.is_file():
|
|
path.chmod(0o444)
|
|
elif path.is_dir():
|
|
path.chmod(0o555)
|
|
self.source.chmod(0o555)
|
|
self.volume_root.chmod(0o755)
|
|
self.releases_root.chmod(0o755)
|
|
|
|
def close(self) -> None:
|
|
if os.name != "nt":
|
|
for path in sorted(
|
|
self.root.rglob("*"), key=lambda item: len(item.parts), reverse=True
|
|
):
|
|
try:
|
|
path.chmod(0o700 if path.is_dir() else 0o600)
|
|
except OSError:
|
|
pass
|
|
self.temporary.cleanup()
|
|
|
|
def docker_runner(
|
|
self, command: list[str], *, cwd: Path | None, timeout: int
|
|
) -> subprocess.CompletedProcess[str]:
|
|
self.command_calls.append(list(command))
|
|
operation = command[3:]
|
|
if operation[:2] == ["buildx", "ls"]:
|
|
rows = ["default|docker", "default|default"]
|
|
if self.builder_present:
|
|
rows += [
|
|
"itworx-mcp-hub-ingestion|docker-container",
|
|
"itworx-mcp-hub-ingestion0|unix:///var/run/docker.sock",
|
|
]
|
|
return subprocess.CompletedProcess(command, 0, "\n".join(rows), "")
|
|
if operation[:2] == ["buildx", "create"]:
|
|
self.assert_no_global_builder_switch(command)
|
|
self.builder_present = True
|
|
return subprocess.CompletedProcess(command, 0, "itworx-mcp-hub-ingestion", "")
|
|
if operation[:2] == ["container", "ls"]:
|
|
names = (
|
|
["buildx_buildkit_itworx-mcp-hub-ingestion0"]
|
|
if self.builder_container_present
|
|
else []
|
|
)
|
|
return subprocess.CompletedProcess(command, 0, "\n".join(names), "")
|
|
if operation[:2] == ["buildx", "inspect"]:
|
|
if "--bootstrap" in operation and timeout < 120:
|
|
raise AssertionError("pinned builder bootstrap needs a bounded pull timeout")
|
|
text = (
|
|
"Name: itworx-mcp-hub-ingestion\n"
|
|
"Driver: docker-container\n\n"
|
|
"Nodes:\n"
|
|
"Name: itworx-mcp-hub-ingestion0\n"
|
|
"Endpoint: unix:///var/run/docker.sock\n"
|
|
f'Driver Options: image="{self._builder_image_option()}"\n'
|
|
)
|
|
if "--bootstrap" in operation:
|
|
self.builder_bootstrapped = True
|
|
self.builder_container_present = True
|
|
if self.builder_bootstrapped:
|
|
text += "Status: running\nBuildKit version: v0.33.0\n"
|
|
else:
|
|
text += "Status: inactive\n"
|
|
return subprocess.CompletedProcess(command, 0, text, "")
|
|
if operation[:2] == ["inspect", "--format"]:
|
|
target = command[-1]
|
|
if target == "buildx_buildkit_itworx-mcp-hub-ingestion0":
|
|
return self._builder_container_inspection(command)
|
|
if (
|
|
operation[:3] == ["image", "inspect", "--format"]
|
|
and command[-1] == self.publisher.FIXED_BUILDKIT_IMAGE
|
|
):
|
|
image_record = {
|
|
"Id": CONFIG_DIGEST,
|
|
"Config.Env": [
|
|
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
|
"BUILDKIT_SETUP_CGROUPV2_ROOT=1",
|
|
],
|
|
"Config.Entrypoint": self.publisher.FIXED_BUILDKIT_ENTRYPOINT,
|
|
"Config.User": "",
|
|
"Config.WorkingDir": "",
|
|
"Config.Labels": {"org.opencontainers.image.title": "BuildKit"},
|
|
}
|
|
raw = "\n".join(
|
|
json.dumps(image_record[field], separators=(",", ":"))
|
|
for field in self.publisher.PINNED_BUILDKIT_IMAGE_FIELDS
|
|
)
|
|
return subprocess.CompletedProcess(command, 0, raw, "")
|
|
if operation[:2] == ["buildx", "build"]:
|
|
self.builder_bootstrapped = True
|
|
metadata_path = Path(command[command.index("--metadata-file") + 1])
|
|
metadata = {
|
|
"containerimage.digest": MANIFEST_DIGEST,
|
|
"containerimage.config.digest": "sha256:" + "9" * 64
|
|
if self.bad_config
|
|
else CONFIG_DIGEST,
|
|
}
|
|
metadata_path.write_text(json.dumps(metadata), encoding="utf-8")
|
|
return subprocess.CompletedProcess(command, 0, "", "")
|
|
if operation[:4] == ["buildx", "imagetools", "inspect", "--format"]:
|
|
descriptor = {
|
|
"digest": "sha256:" + "e" * 64 if self.bad_manifest else MANIFEST_DIGEST,
|
|
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
|
|
"size": 2458,
|
|
}
|
|
return subprocess.CompletedProcess(command, 0, json.dumps(descriptor), "")
|
|
if operation[:2] == ["pull", "--quiet"]:
|
|
return subprocess.CompletedProcess(command, 0, "", "")
|
|
if operation[:2] == ["image", "inspect"]:
|
|
values = [
|
|
CONFIG_DIGEST,
|
|
"10001:10001",
|
|
SOURCE_URI,
|
|
"f" * 40 if self.bad_labels else REVISION,
|
|
TREE,
|
|
REVISION[:12],
|
|
BUILT_AT,
|
|
EPOCH,
|
|
]
|
|
return subprocess.CompletedProcess(command, 0, "|".join(values), "")
|
|
if self.redaction_sentinel in operation:
|
|
raise AssertionError("redaction sentinel must never be an argument")
|
|
raise AssertionError(f"unexpected fake Docker command: {command!r}")
|
|
|
|
def _builder_container_inspection(self, command: list[str]) -> subprocess.CompletedProcess[str]:
|
|
record: dict[str, Any] = {
|
|
"Image": "sha256:" + "0" * 64 if self.bad_builder_actual_image else CONFIG_DIGEST,
|
|
"Config.Image": "moby/buildkit:unexpected"
|
|
if self.bad_builder_container_image
|
|
else self.publisher.FIXED_BUILDKIT_IMAGE,
|
|
"Config.Env": [
|
|
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
|
"BUILDKIT_SETUP_CGROUPV2_ROOT=1",
|
|
],
|
|
"Config.Entrypoint": self.publisher.FIXED_BUILDKIT_ENTRYPOINT,
|
|
"Config.Cmd": self.publisher.FIXED_BUILDKIT_COMMAND,
|
|
"Config.User": "",
|
|
"Config.WorkingDir": "",
|
|
"Config.Labels": {"org.opencontainers.image.title": "BuildKit"},
|
|
"State.Running": self.builder_bootstrapped,
|
|
"HostConfig.Privileged": True,
|
|
"HostConfig.Init": True,
|
|
"HostConfig.RestartPolicy.Name": "unless-stopped",
|
|
"HostConfig.RestartPolicy.MaximumRetryCount": 0,
|
|
"HostConfig.NetworkMode": "default",
|
|
"HostConfig.UsernsMode": "",
|
|
"HostConfig.CgroupParent": "/docker/buildx",
|
|
"HostConfig.CgroupnsMode": "private",
|
|
"HostConfig.Mounts": self._host_mount(),
|
|
"Mounts": [
|
|
{
|
|
"Type": "volume",
|
|
"Name": self.publisher.FIXED_BUILDKIT_STATE_VOLUME,
|
|
"Source": (
|
|
f"{self.publisher.FIXED_DOCKER_ROOT}/volumes/"
|
|
f"{self.publisher.FIXED_BUILDKIT_STATE_VOLUME}/_data"
|
|
),
|
|
"Destination": self.publisher.FIXED_BUILDKIT_STATE_PATH,
|
|
"Driver": "local",
|
|
"Mode": "",
|
|
"RW": True,
|
|
"Propagation": "",
|
|
}
|
|
],
|
|
"HostConfig.Binds": None,
|
|
"HostConfig.Devices": None,
|
|
"HostConfig.DeviceRequests": None,
|
|
"HostConfig.CapAdd": None,
|
|
"HostConfig.CapDrop": None,
|
|
"HostConfig.SecurityOpt": None,
|
|
"HostConfig.PortBindings": None,
|
|
"HostConfig.PublishAllPorts": False,
|
|
"HostConfig.ReadonlyRootfs": False,
|
|
"HostConfig.PidMode": "",
|
|
"HostConfig.IpcMode": "private",
|
|
"HostConfig.UTSMode": "",
|
|
"HostConfig.AutoRemove": False,
|
|
"HostConfig.Runtime": "runc",
|
|
"HostConfig.Memory": 0,
|
|
"HostConfig.MemorySwap": 0,
|
|
"HostConfig.CpuShares": 0,
|
|
"HostConfig.CpuQuota": 0,
|
|
"HostConfig.CpuPeriod": 0,
|
|
"HostConfig.CpusetCpus": "",
|
|
"HostConfig.CpusetMems": "",
|
|
"HostConfig.OomKillDisable": None,
|
|
}
|
|
record.update(self.builder_runtime_overrides)
|
|
raw = "\n".join(
|
|
json.dumps(record[field], separators=(",", ":"))
|
|
for field in self.publisher.BUILDKIT_CONTAINER_FIELDS
|
|
)
|
|
return subprocess.CompletedProcess(command, 0, raw, "")
|
|
|
|
def _host_mount(self, read_only: Any = _OMITTED) -> list[dict[str, Any]]:
|
|
mount: dict[str, Any] = {
|
|
"Type": "volume",
|
|
"Source": self.publisher.FIXED_BUILDKIT_STATE_VOLUME,
|
|
"Target": self.publisher.FIXED_BUILDKIT_STATE_PATH,
|
|
}
|
|
if read_only is not _OMITTED:
|
|
mount["ReadOnly"] = read_only
|
|
return [mount]
|
|
|
|
def assert_no_global_builder_switch(self, command: list[str]) -> None:
|
|
if "--use" in command:
|
|
raise AssertionError("publisher must not switch the global Buildx builder")
|
|
if "--name" not in command or "itworx-mcp-hub-ingestion" not in command:
|
|
raise AssertionError("publisher must use only its fixed dedicated builder")
|
|
if f"image={self.publisher.FIXED_BUILDKIT_IMAGE}" not in command:
|
|
raise AssertionError("publisher must pin the dedicated BuildKit image")
|
|
|
|
def _builder_image_option(self) -> str:
|
|
return "wrong" if self.bad_builder_image else self.publisher.FIXED_BUILDKIT_IMAGE
|
|
|
|
def publisher_module(self) -> Any:
|
|
return self.publisher
|
|
|
|
|
|
class FixedIngestionPublisherTests(unittest.TestCase):
|
|
def setUp(self) -> None:
|
|
self.harness = PublisherHarness()
|
|
self.addCleanup(self.harness.close)
|
|
self.publisher = self.harness.publisher_module()
|
|
|
|
def prepare_builder(self) -> None:
|
|
self.publisher._ensure_dedicated_builder(self.harness.docker_runner, self.harness.frozen)
|
|
|
|
def publish(self) -> dict[str, str]:
|
|
self.publisher._verify_local_release_root(self.harness.source, REVISION)
|
|
self.publisher._ensure_dedicated_builder(self.harness.docker_runner, self.harness.frozen)
|
|
return cast(
|
|
dict[str, str],
|
|
self.publisher._publish_frozen_revision(
|
|
REVISION,
|
|
frozen=self.harness.frozen,
|
|
docker_runner=self.harness.docker_runner,
|
|
source_root=self.harness.source,
|
|
state_root=self.harness.state_root,
|
|
script_path=self.harness.script,
|
|
),
|
|
)
|
|
|
|
def receipt_path(self) -> Path:
|
|
return (
|
|
self.harness.state_root
|
|
/ "mcp-hub-ingestion-publications"
|
|
/ REVISION
|
|
/ "publication.json"
|
|
)
|
|
|
|
def test_builds_fixed_service_with_frozen_labels_pushes_by_digest_and_attests_readback(
|
|
self,
|
|
) -> None:
|
|
original = {
|
|
path.relative_to(self.harness.source).as_posix(): path.read_bytes()
|
|
for path in self.harness.source.rglob("*")
|
|
if path.is_file()
|
|
}
|
|
result = self.publish()
|
|
|
|
build = next(
|
|
command for command in self.harness.command_calls if command[3:5] == ["buildx", "build"]
|
|
)
|
|
self.assertEqual(build[3:5], ["buildx", "build"])
|
|
self.assertIn("--builder", build)
|
|
self.assertIn("itworx-mcp-hub-ingestion", build)
|
|
self.assertEqual(build[build.index("--builder") + 1], self.publisher.FIXED_BUILDER_NAME)
|
|
self.assertIn("--platform", build)
|
|
self.assertEqual(build[build.index("--platform") + 1], "linux/amd64")
|
|
self.assertIn("--provenance=false", build)
|
|
output = build[build.index("--output") + 1]
|
|
self.assertIn("push-by-digest=true", output)
|
|
self.assertNotIn("--tag", build)
|
|
self.assertEqual(
|
|
{build[index + 1] for index, value in enumerate(build[:-1]) if value == "--build-arg"},
|
|
{
|
|
"SERVICE_NAME=connector-ingestion",
|
|
f"GIT_REVISION={REVISION}",
|
|
f"GIT_SOURCE_TREE={TREE}",
|
|
f"IMAGE_VERSION={REVISION[:12]}",
|
|
f"SOURCE_DATE_EPOCH={EPOCH}",
|
|
f"BUILD_DATE={BUILT_AT}",
|
|
},
|
|
)
|
|
self.assertEqual(result["imageRef"], f"{IMAGE_REPOSITORY}@{MANIFEST_DIGEST}")
|
|
self.assertEqual(result["imageId"], CONFIG_DIGEST)
|
|
receipt = json.loads(self.receipt_path().read_text(encoding="utf-8"))
|
|
payload = receipt["receipt"]
|
|
self.assertEqual(payload["imageRef"], result["imageRef"])
|
|
self.assertEqual(payload["sourceFreezeSha256"], self.harness.frozen.freeze_sha256)
|
|
self.assertEqual(
|
|
receipt["receiptSha256"],
|
|
hashlib.sha256(
|
|
(json.dumps(payload, sort_keys=True, separators=(",", ":")) + "\n").encode()
|
|
).hexdigest(),
|
|
)
|
|
self.assertNotIn(
|
|
self.harness.redaction_sentinel,
|
|
self.receipt_path().read_text(encoding="utf-8"),
|
|
)
|
|
self.assertFalse(
|
|
any(command[3:5] == ["login", ""] for command in self.harness.command_calls)
|
|
)
|
|
after = {
|
|
path.relative_to(self.harness.source).as_posix(): path.read_bytes()
|
|
for path in self.harness.source.rglob("*")
|
|
if path.is_file()
|
|
}
|
|
self.assertEqual(original, after)
|
|
if os.name != "nt":
|
|
info = self.receipt_path().stat()
|
|
self.assertEqual(info.st_uid, 0)
|
|
self.assertEqual(info.st_mode & 0o777, 0o600)
|
|
|
|
def test_official_attestation_accepts_only_fixed_repository_and_revision(self) -> None:
|
|
document = {
|
|
"schema": self.publisher.ATTESTATION_SCHEMA,
|
|
"repository": FIXED_REPOSITORY,
|
|
"revision": REVISION,
|
|
"build": dict(self.harness.freeze_build),
|
|
"sourceDateEpoch": EPOCH,
|
|
"freezeSha256": "e" * 64,
|
|
"sourcePath": f"/controller-hub-releases/releases/{REVISION}",
|
|
}
|
|
frozen = self.publisher._validate_frozen_attestation(document, REVISION)
|
|
self.assertEqual(frozen.build, self.harness.freeze_build)
|
|
document["repository"] = "attacker/project"
|
|
with self.assertRaises(self.publisher.PublishError):
|
|
self.publisher._validate_frozen_attestation(document, REVISION)
|
|
|
|
def test_official_attestation_command_is_fixed_read_only_controller_probe(self) -> None:
|
|
expected = {
|
|
"schema": self.publisher.ATTESTATION_SCHEMA,
|
|
"repository": FIXED_REPOSITORY,
|
|
"revision": REVISION,
|
|
"build": dict(self.harness.freeze_build),
|
|
"sourceDateEpoch": EPOCH,
|
|
"freezeSha256": "e" * 64,
|
|
"sourcePath": f"/controller-hub-releases/releases/{REVISION}",
|
|
}
|
|
|
|
def runner(
|
|
command: list[str], *, cwd: Path | None, timeout: int
|
|
) -> subprocess.CompletedProcess[str]:
|
|
self.assertEqual(command[0:4], ["/usr/bin/docker", "--context", "default", "exec"])
|
|
self.assertIn(self.publisher.FIXED_CONTAINER, command)
|
|
self.assertIn("python3", command)
|
|
self.assertIn("-c", command)
|
|
self.assertNotIn("bash", command)
|
|
return subprocess.CompletedProcess(command, 0, json.dumps(expected), "")
|
|
|
|
result = self.publisher._attest_official_freeze(REVISION, runner)
|
|
self.assertEqual(result.revision, REVISION)
|
|
|
|
def test_engine_preflight_requires_same_fixed_host_and_controller_socket_engine(self) -> None:
|
|
def runner(
|
|
command: list[str], *, cwd: Path | None, timeout: int
|
|
) -> subprocess.CompletedProcess[str]:
|
|
if command[1:3] == ["context", "show"]:
|
|
return subprocess.CompletedProcess(command, 0, "default", "")
|
|
if command[1:3] == ["context", "inspect"]:
|
|
return subprocess.CompletedProcess(command, 0, "unix:///var/run/docker.sock", "")
|
|
operation = command[3:]
|
|
if operation[:1] == ["info"]:
|
|
return subprocess.CompletedProcess(
|
|
command, 0, f"{ENGINE_ID}|/var/lib/docker|27.5.1|Tower", ""
|
|
)
|
|
if operation[:2] == ["exec", "--user"]:
|
|
return subprocess.CompletedProcess(
|
|
command, 0, f"{ENGINE_ID}|/var/lib/docker|27.5.1|Tower", ""
|
|
)
|
|
if operation[:2] == ["inspect", "--format"]:
|
|
return subprocess.CompletedProcess(command, 0, f"{CONTAINER_ID}|true", "")
|
|
if operation[:2] == ["buildx", "version"]:
|
|
return subprocess.CompletedProcess(
|
|
command, 0, "github.com/docker/buildx v0.20.1 abc123", ""
|
|
)
|
|
raise AssertionError(f"unexpected preflight command: {command!r}")
|
|
|
|
engine, container = self.publisher._preflight_engine(runner)
|
|
self.assertEqual(engine, ENGINE_ID)
|
|
self.assertEqual(container, CONTAINER_ID)
|
|
|
|
def test_engine_preflight_rejects_unreviewed_buildx_before_publication(self) -> None:
|
|
def runner(
|
|
command: list[str], *, cwd: Path | None, timeout: int
|
|
) -> subprocess.CompletedProcess[str]:
|
|
if command[1:3] == ["context", "show"]:
|
|
return subprocess.CompletedProcess(command, 0, "default", "")
|
|
if command[1:3] == ["context", "inspect"]:
|
|
return subprocess.CompletedProcess(command, 0, "unix:///var/run/docker.sock", "")
|
|
operation = command[3:]
|
|
if operation[:1] == ["info"]:
|
|
return subprocess.CompletedProcess(
|
|
command, 0, f"{ENGINE_ID}|/var/lib/docker|27.5.1|Tower", ""
|
|
)
|
|
if operation[:2] == ["exec", "--user"]:
|
|
return subprocess.CompletedProcess(
|
|
command, 0, f"{ENGINE_ID}|/var/lib/docker|27.5.1|Tower", ""
|
|
)
|
|
if operation[:2] == ["inspect", "--format"]:
|
|
return subprocess.CompletedProcess(command, 0, f"{CONTAINER_ID}|true", "")
|
|
if operation[:2] == ["buildx", "version"]:
|
|
return subprocess.CompletedProcess(
|
|
command, 0, "github.com/docker/buildx v0.21.3", ""
|
|
)
|
|
raise AssertionError(f"unexpected preflight command: {command!r}")
|
|
|
|
with self.assertRaises(self.publisher.PublishError):
|
|
self.publisher._preflight_engine(runner)
|
|
|
|
def test_engine_preflight_rejects_controller_socket_mismatch_before_build(self) -> None:
|
|
def runner(
|
|
command: list[str], *, cwd: Path | None, timeout: int
|
|
) -> subprocess.CompletedProcess[str]:
|
|
if command[1:3] == ["context", "show"]:
|
|
return subprocess.CompletedProcess(command, 0, "default", "")
|
|
if command[1:3] == ["context", "inspect"]:
|
|
return subprocess.CompletedProcess(command, 0, "unix:///var/run/docker.sock", "")
|
|
operation = command[3:]
|
|
if operation[:1] == ["info"]:
|
|
return subprocess.CompletedProcess(
|
|
command, 0, f"{ENGINE_ID}|/var/lib/docker|27.5.1|Tower", ""
|
|
)
|
|
if operation[:2] == ["exec", "--user"]:
|
|
return subprocess.CompletedProcess(
|
|
command, 0, f"{'0' * 64}|/var/lib/docker|27.5.1|Tower", ""
|
|
)
|
|
raise AssertionError("preflight proceeded after an engine mismatch")
|
|
|
|
with self.assertRaises(self.publisher.PublishError):
|
|
self.publisher._preflight_engine(runner)
|
|
|
|
def test_engine_identity_requires_fixed_tower_hostname(self) -> None:
|
|
with self.assertRaises(self.publisher.PublishError):
|
|
self.publisher._parse_engine_identity(
|
|
f"{ENGINE_ID}|/var/lib/docker|27.5.1|another-host", source="host"
|
|
)
|
|
|
|
def test_environment_overrides_cannot_redirect_engine_builder_or_auth_config(self) -> None:
|
|
for name in (
|
|
"DOCKER_HOST",
|
|
"DOCKER_CONTEXT",
|
|
"DOCKER_CONFIG",
|
|
"BUILDX_BUILDER",
|
|
"BUILDX_CONFIG",
|
|
"DOCKER_AUTH_CONFIG",
|
|
):
|
|
with self.subTest(name=name), self.assertRaises(self.publisher.PublishError):
|
|
self.publisher._reject_docker_environment({"HOME": "/root", name: "sentinel"})
|
|
|
|
def test_dedicated_builder_is_created_only_after_freeze_and_does_not_switch_default(
|
|
self,
|
|
) -> None:
|
|
self.publisher._ensure_dedicated_builder(self.harness.docker_runner, self.harness.frozen)
|
|
create = next(
|
|
command
|
|
for command in self.harness.command_calls
|
|
if command[3:5] == ["buildx", "create"]
|
|
)
|
|
self.harness.assert_no_global_builder_switch(create)
|
|
self.assertIn("docker-container", create)
|
|
self.assertIn("default", create)
|
|
self.assertTrue(self.harness.builder_present)
|
|
|
|
def test_mismatched_preexisting_dedicated_builder_is_denied(self) -> None:
|
|
self.harness.builder_present = True
|
|
|
|
def wrong_builder(
|
|
command: list[str], *, cwd: Path | None, timeout: int
|
|
) -> subprocess.CompletedProcess[str]:
|
|
self.harness.command_calls.append(list(command))
|
|
if command[3:5] == ["buildx", "ls"]:
|
|
return subprocess.CompletedProcess(
|
|
command,
|
|
0,
|
|
"default|docker\ndefault|default\nitworx-mcp-hub-ingestion|docker\nitworx-mcp-hub-ingestion0|default",
|
|
"",
|
|
)
|
|
if command[3:5] == ["container", "ls"]:
|
|
return subprocess.CompletedProcess(command, 0, "", "")
|
|
raise AssertionError("mismatched builder should be rejected from inventory")
|
|
|
|
with self.assertRaises(self.publisher.PublishError):
|
|
self.publisher._ensure_dedicated_builder(wrong_builder, self.harness.frozen)
|
|
self.assertFalse(
|
|
any(command[3:5] == ["buildx", "build"] for command in self.harness.command_calls)
|
|
)
|
|
|
|
def test_preexisting_builder_container_image_is_checked_before_bootstrap(self) -> None:
|
|
self.harness.builder_present = True
|
|
self.harness.builder_container_present = True
|
|
self.harness.bad_builder_container_image = True
|
|
with self.assertRaises(self.publisher.PublishError):
|
|
self.publisher._ensure_dedicated_builder(
|
|
self.harness.docker_runner, self.harness.frozen
|
|
)
|
|
self.assertFalse(
|
|
any(
|
|
command[3:6] == ["buildx", "inspect", "--bootstrap"]
|
|
or command[3:5] == ["buildx", "build"]
|
|
for command in self.harness.command_calls
|
|
)
|
|
)
|
|
|
|
def test_preexisting_builder_container_actual_image_id_is_checked_before_bootstrap(
|
|
self,
|
|
) -> None:
|
|
self.harness.builder_present = True
|
|
self.harness.builder_container_present = True
|
|
self.harness.bad_builder_actual_image = True
|
|
with self.assertRaises(self.publisher.PublishError):
|
|
self.publisher._ensure_dedicated_builder(
|
|
self.harness.docker_runner, self.harness.frozen
|
|
)
|
|
self.assertFalse(
|
|
any(
|
|
command[3:6] == ["buildx", "inspect", "--bootstrap"]
|
|
or command[3:5] == ["buildx", "build"]
|
|
for command in self.harness.command_calls
|
|
)
|
|
)
|
|
|
|
def test_preexisting_builder_container_unsafe_runtime_is_denied_before_bootstrap(self) -> None:
|
|
unsafe_configurations: tuple[dict[str, Any], ...] = (
|
|
{"HostConfig.Privileged": False},
|
|
{"HostConfig.SecurityOpt": ["seccomp=unconfined"]},
|
|
{"HostConfig.NetworkMode": "host"},
|
|
{"HostConfig.IpcMode": "host"},
|
|
{"HostConfig.Runtime": "foreign"},
|
|
{"HostConfig.CgroupnsMode": "host"},
|
|
{"HostConfig.Mounts": []},
|
|
{"Config.Env": ["TOKEN=sentinel-value-must-not-escape"]},
|
|
)
|
|
for override in unsafe_configurations:
|
|
with self.subTest(override=tuple(override)):
|
|
self.harness.command_calls.clear()
|
|
self.harness.builder_present = True
|
|
self.harness.builder_container_present = True
|
|
self.harness.builder_bootstrapped = False
|
|
self.harness.builder_runtime_overrides = override
|
|
with self.assertRaises(self.publisher.PublishError) as raised:
|
|
self.publisher._ensure_dedicated_builder(
|
|
self.harness.docker_runner, self.harness.frozen
|
|
)
|
|
self.assertNotIn("sentinel-value-must-not-escape", str(raised.exception))
|
|
self.assertFalse(
|
|
any(
|
|
command[3:6] == ["buildx", "inspect", "--bootstrap"]
|
|
or command[3:5] == ["buildx", "build"]
|
|
for command in self.harness.command_calls
|
|
)
|
|
)
|
|
|
|
def test_writable_builder_state_mount_accepts_only_omitted_or_boolean_false(self) -> None:
|
|
self.harness.builder_present = True
|
|
self.harness.builder_container_present = True
|
|
self.harness.builder_bootstrapped = True
|
|
self.publisher._verify_dedicated_builder_container(
|
|
self.harness.docker_runner, require_running=True
|
|
)
|
|
|
|
self.harness.builder_runtime_overrides = {
|
|
"HostConfig.Mounts": self.harness._host_mount(False)
|
|
}
|
|
self.publisher._verify_dedicated_builder_container(
|
|
self.harness.docker_runner, require_running=True
|
|
)
|
|
|
|
for unsafe_value in (True, None, 0, "false"):
|
|
with self.subTest(read_only=unsafe_value):
|
|
self.harness.command_calls.clear()
|
|
self.harness.builder_runtime_overrides = {
|
|
"HostConfig.Mounts": self.harness._host_mount(unsafe_value)
|
|
}
|
|
with self.assertRaises(self.publisher.PublishError):
|
|
self.publisher._ensure_dedicated_builder(
|
|
self.harness.docker_runner, self.harness.frozen
|
|
)
|
|
self.assertFalse(
|
|
any(
|
|
command[3:6] == ["buildx", "inspect", "--bootstrap"]
|
|
or command[3:5] == ["buildx", "build"]
|
|
for command in self.harness.command_calls
|
|
)
|
|
)
|
|
|
|
def test_default_buildkit_config_file_blocks_builder_before_docker_commands(self) -> None:
|
|
config = self.harness.root / "buildkitd.default.toml"
|
|
config.write_text("[worker.oci]\n", encoding="utf-8")
|
|
self.publisher.FIXED_BUILDKIT_CONFIG_PATH = config
|
|
with self.assertRaises(self.publisher.PublishError):
|
|
self.publisher._ensure_dedicated_builder(
|
|
self.harness.docker_runner, self.harness.frozen
|
|
)
|
|
self.assertEqual(self.harness.command_calls, [])
|
|
|
|
@unittest.skipIf(os.name == "nt", "symlink behavior is POSIX-specific")
|
|
def test_default_buildkit_config_symlink_blocks_builder_before_docker_commands(self) -> None:
|
|
target = self.harness.root / "outside.toml"
|
|
target.write_text("[worker.oci]\n", encoding="utf-8")
|
|
link = self.harness.root / "buildkitd.default.toml"
|
|
link.symlink_to(target)
|
|
self.publisher.FIXED_BUILDKIT_CONFIG_PATH = link
|
|
with self.assertRaises(self.publisher.PublishError):
|
|
self.publisher._ensure_dedicated_builder(
|
|
self.harness.docker_runner, self.harness.frozen
|
|
)
|
|
self.assertEqual(self.harness.command_calls, [])
|
|
|
|
def test_orphan_reserved_container_blocks_create_bootstrap_and_build(self) -> None:
|
|
self.harness.builder_container_present = True
|
|
self.harness.bad_builder_container_image = True
|
|
with self.assertRaises(self.publisher.PublishError):
|
|
self.publisher._ensure_dedicated_builder(
|
|
self.harness.docker_runner, self.harness.frozen
|
|
)
|
|
self.assertFalse(
|
|
any(
|
|
command[3:5] == ["buildx", "create"]
|
|
or command[3:6] == ["buildx", "inspect", "--bootstrap"]
|
|
or command[3:5] == ["buildx", "build"]
|
|
for command in self.harness.command_calls
|
|
)
|
|
)
|
|
|
|
def test_builder_creation_requires_a_validated_frozen_source(self) -> None:
|
|
invalid = self.harness.frozen.__class__(
|
|
repository="attacker/project",
|
|
revision=REVISION,
|
|
build=dict(self.harness.freeze_build),
|
|
source_date_epoch=EPOCH,
|
|
freeze_sha256="e" * 64,
|
|
controller_source_path=f"/controller-hub-releases/releases/{REVISION}",
|
|
)
|
|
with self.assertRaises(self.publisher.PublishError):
|
|
self.publisher._ensure_dedicated_builder(self.harness.docker_runner, invalid)
|
|
self.assertEqual(self.harness.command_calls, [])
|
|
|
|
def test_rejects_stale_or_writable_staged_source_before_build(self) -> None:
|
|
dockerfile = (
|
|
self.harness.source / "infrastructure" / "images" / "python-service" / "Dockerfile"
|
|
)
|
|
if os.name != "nt":
|
|
dockerfile.chmod(0o644)
|
|
with self.assertRaises(self.publisher.PublishError):
|
|
self.publish()
|
|
else:
|
|
with self.assertRaises(self.publisher.PublishError):
|
|
self.publisher._verify_local_release_root(self.harness.source.parent, REVISION)
|
|
self.assertFalse(
|
|
any(command[3:5] == ["buildx", "build"] for command in self.harness.command_calls)
|
|
)
|
|
self.assertFalse(self.receipt_path().exists())
|
|
|
|
def test_rejects_bad_build_metadata_and_registry_manifest_digest(self) -> None:
|
|
self.harness.bad_manifest = True
|
|
with self.assertRaises(self.publisher.PublishError):
|
|
self.publish()
|
|
self.assertFalse(self.receipt_path().exists())
|
|
|
|
def test_rejects_wrong_config_id_or_provenance_labels_without_receipt(self) -> None:
|
|
self.harness.bad_config = True
|
|
with self.assertRaises(self.publisher.PublishError):
|
|
self.publish()
|
|
self.assertFalse(self.receipt_path().exists())
|
|
self.harness.bad_config = False
|
|
self.harness.bad_labels = True
|
|
with self.assertRaises(self.publisher.PublishError):
|
|
self.publish()
|
|
self.assertFalse(self.receipt_path().exists())
|
|
|
|
def test_child_error_output_is_scrubbed_and_not_saved(self) -> None:
|
|
self.prepare_builder()
|
|
|
|
def failed_runner(
|
|
command: list[str], *, cwd: Path | None, timeout: int
|
|
) -> subprocess.CompletedProcess[str]:
|
|
if command[3:5] == ["buildx", "build"]:
|
|
return subprocess.CompletedProcess(command, 1, "", self.harness.redaction_sentinel)
|
|
return self.harness.docker_runner(command, cwd=cwd, timeout=timeout)
|
|
|
|
with self.assertRaises(self.publisher.PublishError) as raised:
|
|
self.publisher._publish_frozen_revision(
|
|
REVISION,
|
|
frozen=self.harness.frozen,
|
|
docker_runner=failed_runner,
|
|
source_root=self.harness.source,
|
|
state_root=self.harness.state_root,
|
|
script_path=self.harness.script,
|
|
)
|
|
self.assertNotIn(self.harness.redaction_sentinel, str(raised.exception))
|
|
self.assertFalse(self.receipt_path().exists())
|
|
|
|
def test_preexisting_receipt_is_never_overwritten_or_rebuilt(self) -> None:
|
|
self.prepare_builder()
|
|
receipt = self.receipt_path()
|
|
receipt.parent.mkdir(parents=True, mode=0o700)
|
|
receipt.write_text("prior immutable receipt", encoding="utf-8")
|
|
before = len(self.harness.command_calls)
|
|
with self.assertRaises(self.publisher.PublishError):
|
|
self.publisher._publish_frozen_revision(
|
|
REVISION,
|
|
frozen=self.harness.frozen,
|
|
docker_runner=self.harness.docker_runner,
|
|
source_root=self.harness.source,
|
|
state_root=self.harness.state_root,
|
|
script_path=self.harness.script,
|
|
)
|
|
self.assertEqual(receipt.read_text(encoding="utf-8"), "prior immutable receipt")
|
|
self.assertEqual(len(self.harness.command_calls), before)
|
|
|
|
def test_production_slot_check_denies_existing_receipt_without_docker_commands(self) -> None:
|
|
receipt = self.receipt_path()
|
|
receipt.parent.mkdir(parents=True, mode=0o700)
|
|
receipt.write_text("prior immutable receipt", encoding="utf-8")
|
|
with self.assertRaises(self.publisher.PublishError):
|
|
self.publisher._require_publication_slot(self.harness.state_root, REVISION)
|
|
self.assertEqual(self.harness.command_calls, [])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|