fix: verify full prebuilt images before offline production deployment
Community checks / verify (push) Skipped
Verify Frame Flow / verify (push) Successful in 5m37s

This commit is contained in:
渡口浪人
2026-10-18 19:45:30 +08:00
parent cb8ac32b74
commit 50bb41899d
5 changed files with 121 additions and 22 deletions
+60 -17
View File
@@ -127,6 +127,48 @@ def main():
release(lock)
def verify_prebuilt_image(image, commit, version, hashes):
expected = os.getenv("FRAME_FLOW_PREBUILT_IMAGE_ID", "")
if not expected:
return False
assert re.fullmatch(r"sha256:[0-9a-f]{64}", expected), "Require immutable image ID"
metadata = json.loads(run("docker", "image", "inspect", image))[0]
assert metadata["Id"] == expected, "Prebuilt image ID mismatch"
labels = metadata["Config"].get("Labels") or {}
assert labels.get("org.opencontainers.image.revision") == commit
assert labels.get("org.opencontainers.image.version") == version
project = {
n: h
for n, h in hashes.items()
if n.startswith(("pigway_frame_flow/", "vendor/"))
or n in {"requirements.lock", "LICENSE", "NOTICE.md"}
}
# Validate the artifact before it can access production config or data.
code = "import hashlib,json,pathlib,sys; h=json.load(sys.stdin); assert h and all(hashlib.sha256((pathlib.Path('/app')/n).read_bytes()).hexdigest()==v for n,v in h.items())"
subprocess.run(
[
"docker",
"run",
"--rm",
"-i",
"--network=none",
"--read-only",
"--cap-drop=ALL",
"--security-opt=no-new-privileges",
"--user=10333:10333",
"--entrypoint=python",
expected,
"-c",
code,
],
input=json.dumps(project),
text=True,
check=True,
timeout=60,
)
return True
def release(lock):
ctx = Path(__file__).resolve().parent.parent
assert ctx.parent == ROOT / "migration-inbox"
@@ -154,23 +196,24 @@ def release(lock):
version = tomllib.loads((ctx / "pyproject.toml").read_text())["project"]["version"]
assert re.fullmatch(r"[0-9]+\.[0-9]+\.[0-9]+", version)
image = "pigway-frame-flow:" + version + "-" + commit[:12]
# A source-only overlay would retain vulnerable packages from the old image.
run(
"docker",
"build",
"--pull",
"-f",
str(ctx / "Dockerfile"),
"--build-arg",
"BUILD_COMMIT=" + commit,
"--build-arg",
"BUILD_TIME=" + stamp,
"--build-arg",
"ALPINE_MIRROR=" + os.getenv("ALPINE_MIRROR", "dl-cdn.alpinelinux.org"),
"-t",
image,
str(ctx),
)
if not verify_prebuilt_image(image, commit, version, hashes):
# A source-only overlay would retain vulnerable packages from the old image.
run(
"docker",
"build",
"--pull",
"-f",
str(ctx / "Dockerfile"),
"--build-arg",
"BUILD_COMMIT=" + commit,
"--build-arg",
"BUILD_TIME=" + stamp,
"--build-arg",
"ALPINE_MIRROR=" + os.getenv("ALPINE_MIRROR", "dl-cdn.alpinelinux.org"),
"-t",
image,
str(ctx),
)
compose = json.loads((APP / "compose.json").read_text())
service = compose["services"][CONTAINER]
service["image"] = image