fix(security): stage multi-platform runtime image
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 1m16s
CD Pipeline / build-and-deploy (push) Failing after 4m9s
CD Pipeline / post-deploy-checks (push) Has been skipped

This commit is contained in:
ogt
2026-07-15 09:22:14 +08:00
parent dcaecb6801
commit 41c069875c
3 changed files with 135 additions and 13 deletions

View File

@@ -603,9 +603,25 @@ def _registry_descriptor(image_ref: str) -> RegistryDescriptor | None:
)
def _local_config_digest(image_ref: str) -> str:
output = _run(["docker", "image", "inspect", "--format={{.Id}}", image_ref]).stdout
return _require_digest((output or "").strip(), "local_config_digest")
def _local_platform_digest(image_ref: str, platform: str) -> str:
output = _run(
[
"docker",
"image",
"inspect",
"--platform",
platform,
"--format={{json .Descriptor}}",
image_ref,
]
).stdout
try:
descriptor = json.loads(output or "{}")
except json.JSONDecodeError as exc:
raise ControllerError("local_platform_descriptor_invalid") from exc
if not isinstance(descriptor, dict):
raise ControllerError("local_platform_descriptor_invalid")
return _require_digest(descriptor.get("digest"), "local_platform_digest")
def _local_image_present(image_ref: str) -> bool:
@@ -675,14 +691,30 @@ def mirror_images(
if not _archive_contains_digest(archive, image.platform_digest):
raise ControllerError("runtime_cache_export_digest_missing")
_run(
["docker", "load", "--input", str(archive)],
[
"docker",
"load",
"--platform",
policy.platform,
"--input",
str(archive),
],
quiet=True,
)
_run(
["docker", "tag", source_ref, image.push_ref],
quiet=True,
)
_run(["docker", "push", image.push_ref], quiet=True)
_run(
[
"docker",
"push",
"--platform",
policy.platform,
image.push_ref,
],
quiet=True,
)
finally:
_remove_local_image(image.push_ref)
if not source_preexisting:
@@ -763,17 +795,40 @@ def stage_images(
cache.export(source_ref, archive)
if not _archive_contains_digest(archive, image.platform_digest):
raise ControllerError("runtime_cache_export_digest_missing")
if not _archive_contains_digest(archive, source_config_digest):
raise ControllerError(
"runtime_cache_export_config_digest_missing"
)
_run(
["docker", "load", "--input", str(archive)],
[
"docker",
"load",
"--platform",
policy.platform,
"--input",
str(archive),
],
quiet=True,
)
if _local_config_digest(source_ref) != source_config_digest:
raise ControllerError("local_image_config_digest_mismatch")
if (
_local_platform_digest(source_ref, policy.platform)
!= image.platform_digest
):
raise ControllerError("local_image_platform_digest_mismatch")
_run(
["docker", "tag", source_ref, image.push_ref],
quiet=True,
)
_run(["docker", "push", image.push_ref], quiet=True)
_run(
[
"docker",
"push",
"--platform",
policy.platform,
image.push_ref,
],
quiet=True,
)
finally:
_remove_local_image(image.push_ref)
if not source_preexisting: