feat(icu): Add verification support for multi-arch images

This commit is contained in:
Alexis Métaireau 2025-02-05 14:27:44 +01:00
parent e67fbc1e72
commit 94e51840e7
No known key found for this signature in database
GPG key ID: C65C7A89A8FFC56E
3 changed files with 19 additions and 5 deletions

View file

@ -192,13 +192,22 @@ def container_pull(image: str) -> bool:
return process.returncode == 0 return process.returncode == 0
def get_local_image_hash(image: str) -> Optional[str]: def get_local_image_digest(image: str) -> Optional[str]:
""" """
Returns a image hash from a local image name Returns a image hash from a local image name
""" """
cmd = [get_runtime_name(), "image", "inspect", image, "-f", "{{.Digest}}"] # Get the image hash from the podman images command, as
# podman inspect returns a the digest of the architecture-bound image
cmd = [get_runtime_name(), "images", image, "--format", "{{.Digest}}"]
log.debug(" ".join(cmd))
try: try:
result = subprocess.run(cmd, capture_output=True, check=True) result = subprocess.run(cmd, capture_output=True, check=True)
lines = result.stdout.decode().strip().split("\n")
if len(lines) != 1:
raise errors.MultipleImagesFoundException(
f"Expected a single line of output, got {len(lines)} lines"
)
return lines[0].replace("sha256:", "")
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
return None return None
else: else:

View file

@ -126,6 +126,10 @@ class ImageNotPresentException(Exception):
pass pass
class MultipleImagesFoundException(Exception):
pass
class ImageInstallationException(Exception): class ImageInstallationException(Exception):
pass pass

View file

@ -105,7 +105,7 @@ def verify_signature(signature: dict, image_hash: str, pubkey: str) -> bool:
def new_image_release(image: str) -> bool: def new_image_release(image: str) -> bool:
remote_hash = registry.get_manifest_hash(image) remote_hash = registry.get_manifest_hash(image)
local_hash = runtime.get_local_image_hash(image) local_hash = runtime.get_local_image_digest(image)
log.debug("Remote hash: %s", remote_hash) log.debug("Remote hash: %s", remote_hash)
log.debug("Local hash: %s", local_hash) log.debug("Local hash: %s", local_hash)
return remote_hash != local_hash return remote_hash != local_hash
@ -181,7 +181,8 @@ def upgrade_container_image_airgapped(container_tar: str, pubkey: str) -> str:
index_json["manifests"] = [ index_json["manifests"] = [
manifest manifest
for manifest in index_json["manifests"] for manifest in index_json["manifests"]
if manifest["annotations"].get("kind") != "dev.cosignproject.cosign/sigs" if manifest["annotations"].get("kind")
in ("dev.cosignproject.cosign/imageIndex", "dev.cosignproject.cosign/image")
] ]
with open(signature_filename, "rb") as f: with open(signature_filename, "rb") as f:
@ -317,7 +318,7 @@ def verify_local_image(image: str, pubkey: str) -> bool:
""" """
log.info(f"Verifying local image {image} against pubkey {pubkey}") log.info(f"Verifying local image {image} against pubkey {pubkey}")
try: try:
image_hash = runtime.get_local_image_hash(image) image_hash = runtime.get_local_image_digest(image)
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
raise errors.ImageNotFound(f"The image {image} does not exist locally") raise errors.ImageNotFound(f"The image {image} does not exist locally")