diff --git a/dangerzone/updater/attestations.py b/dangerzone/updater/attestations.py index c7d0a87dc..3028ec3ec 100644 --- a/dangerzone/updater/attestations.py +++ b/dangerzone/updater/attestations.py @@ -1,6 +1,8 @@ import subprocess from tempfile import NamedTemporaryFile +from . import utils + def verify_attestation( manifest: bytes, attestation_bundle: bytes, image_tag: str, expected_repo: str @@ -9,6 +11,7 @@ def verify_attestation( Look up the image attestation to see if the image has been built on Github runners, and from a given repository. """ + utils.ensure_cosign() # Put the value in files and verify with cosign with ( diff --git a/dangerzone/updater/errors.py b/dangerzone/updater/errors.py index 40dd1dc91..72979918f 100644 --- a/dangerzone/updater/errors.py +++ b/dangerzone/updater/errors.py @@ -36,3 +36,7 @@ class SignatureMismatch(SignatureError): class LocalSignatureNotFound(SignatureError): pass + + +class CosignNotInstalledError(SignatureError): + pass diff --git a/dangerzone/updater/registry.py b/dangerzone/updater/registry.py index 306616ea0..2fd4ecaaa 100644 --- a/dangerzone/updater/registry.py +++ b/dangerzone/updater/registry.py @@ -12,6 +12,8 @@ "list_tags", "get_manifest", "get_attestation", + "Image", + "parse_image_location", ] SIGSTORE_BUNDLE = "application/vnd.dev.sigstore.bundle.v0.3+json" diff --git a/dangerzone/updater/signatures.py b/dangerzone/updater/signatures.py index 655c2a31b..898d95ba2 100644 --- a/dangerzone/updater/signatures.py +++ b/dangerzone/updater/signatures.py @@ -9,7 +9,7 @@ from typing import Dict, List, Tuple from ..container_utils import container_pull, load_image_hash -from . import errors, log +from . import errors, log, utils from .registry import get_manifest_hash try: @@ -32,14 +32,6 @@ def get_config_dir() -> Path: ] -def is_cosign_installed() -> bool: - try: - subprocess.run(["cosign", "version"], capture_output=True, check=True) - return True - except subprocess.CalledProcessError: - return False - - def signature_to_bundle(sig: Dict) -> Dict: """Convert a cosign-download signature to the format expected by cosign bundle.""" bundle = sig["Bundle"] @@ -65,6 +57,7 @@ def signature_to_bundle(sig: Dict) -> Dict: def verify_signature(signature: dict, pubkey: str) -> bool: """Verify a signature against a given public key""" + utils.ensure_cosign() signature_bundle = signature_to_bundle(signature) with ( @@ -221,6 +214,7 @@ def get_signatures(image: str, hash: str) -> List[Dict]: """ Retrieve the signatures from cosign download signature and convert each one to the "cosign bundle" format. """ + utils.ensure_cosign() process = subprocess.run( ["cosign", "download", "signature", f"{image}@sha256:{hash}"], diff --git a/dangerzone/updater/utils.py b/dangerzone/updater/utils.py new file mode 100644 index 000000000..a97a49e10 --- /dev/null +++ b/dangerzone/updater/utils.py @@ -0,0 +1,10 @@ +import subprocess + +from . import errors + + +def ensure_cosign() -> None: + try: + subprocess.run(["cosign", "version"], capture_output=True, check=True) + except subprocess.CalledProcessError: + raise errors.CosignNotInstalledError()