Compare commits

..

1 commit

Author SHA1 Message Date
63c9f4ed50
Merge 5bd51575fe into a6aa66f925 2025-03-03 15:06:33 +00:00
3 changed files with 17 additions and 33 deletions

View file

@ -10,7 +10,6 @@ from .util import get_resource_path, get_subprocess_startupinfo
OLD_CONTAINER_NAME = "dangerzone.rocks/dangerzone" OLD_CONTAINER_NAME = "dangerzone.rocks/dangerzone"
CONTAINER_NAME = "ghcr.io/almet/dangerzone/dangerzone" # FIXME: Change this to the correct container name CONTAINER_NAME = "ghcr.io/almet/dangerzone/dangerzone" # FIXME: Change this to the correct container name
RUNTIME_NAME = "podman" if platform.system() == "Linux" else "docker"
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -21,7 +20,10 @@ def subprocess_run(*args, **kwargs) -> subprocess.CompletedProcess:
def get_runtime_name() -> str: def get_runtime_name() -> str:
return RUNTIME_NAME if platform.system() == "Linux":
return "podman"
# Windows, Darwin, and unknown use docker for now, dangerzone-vm eventually
return "docker"
def get_runtime_version() -> Tuple[int, int]: def get_runtime_version() -> Tuple[int, int]:
@ -187,6 +189,7 @@ def container_pull(image: str, manifest_digest: str, callback: Callable):
stderr=subprocess.STDOUT, stderr=subprocess.STDOUT,
text=True, text=True,
bufsize=1, bufsize=1,
universal_newlines=True,
) )
for line in process.stdout: # type: ignore for line in process.stdout: # type: ignore

View file

@ -1,12 +1,9 @@
#!/usr/bin/python #!/usr/bin/python
import functools
import logging import logging
import click import click
from .. import container_utils
from ..container_utils import get_runtime_name
from . import attestations, errors, log, registry, signatures from . import attestations, errors, log, registry, signatures
DEFAULT_REPOSITORY = "freedomofpress/dangerzone" DEFAULT_REPOSITORY = "freedomofpress/dangerzone"
@ -16,8 +13,7 @@ DEFAULT_IMAGE_NAME = "ghcr.io/freedomofpress/dangerzone/dangerzone"
@click.group() @click.group()
@click.option("--debug", is_flag=True) @click.option("--debug", is_flag=True)
@click.option("--runtime", default=get_runtime_name()) def main(debug: bool) -> None:
def main(debug: bool, runtime: str) -> None:
if debug: if debug:
click.echo("Debug mode enabled") click.echo("Debug mode enabled")
level = logging.DEBUG level = logging.DEBUG
@ -25,10 +21,6 @@ def main(debug: bool, runtime: str) -> None:
level = logging.INFO level = logging.INFO
logging.basicConfig(level=level) logging.basicConfig(level=level)
if runtime != get_runtime_name():
click.echo(f"Using container runtime: {runtime}")
container_utils.RUNTIME_NAME = runtime
@main.command() @main.command()
@click.argument("image", default=DEFAULT_IMAGE_NAME) @click.argument("image", default=DEFAULT_IMAGE_NAME)
@ -36,10 +28,8 @@ def main(debug: bool, runtime: str) -> None:
def upgrade(image: str, pubkey: str) -> None: def upgrade(image: str, pubkey: str) -> None:
"""Upgrade the image to the latest signed version.""" """Upgrade the image to the latest signed version."""
manifest_digest = registry.get_manifest_digest(image) manifest_digest = registry.get_manifest_digest(image)
try: try:
callback = functools.partial(click.echo, nl=False) signatures.upgrade_container_image(image, manifest_digest, pubkey)
signatures.upgrade_container_image(image, manifest_digest, pubkey, callback)
click.echo(f"✅ The local image {image} has been upgraded") click.echo(f"✅ The local image {image} has been upgraded")
click.echo(f"✅ The image has been signed with {pubkey}") click.echo(f"✅ The image has been signed with {pubkey}")
click.echo(f"✅ Signatures has been verified and stored locally") click.echo(f"✅ Signatures has been verified and stored locally")
@ -66,23 +56,17 @@ def store_signatures(image: str, pubkey: str) -> None:
@main.command() @main.command()
@click.argument("image_filename") @click.argument("image_filename")
@click.option("--pubkey", default=signatures.DEFAULT_PUBKEY_LOCATION) @click.option("--pubkey", default=signatures.DEFAULT_PUBKEY_LOCATION)
@click.option("--force", is_flag=True) def load_archive(image_filename: str, pubkey: str) -> None:
def load_archive(image_filename: str, pubkey: str, force: bool) -> None:
"""Upgrade the local image to the one in the archive.""" """Upgrade the local image to the one in the archive."""
try: try:
loaded_image = signatures.upgrade_container_image_airgapped( loaded_image = signatures.upgrade_container_image_airgapped(
image_filename, pubkey, bypass_logindex=force image_filename, pubkey
) )
click.echo( click.echo(
f"✅ Installed image {image_filename} on the system as {loaded_image}" f"✅ Installed image {image_filename} on the system as {loaded_image}"
) )
except errors.ImageAlreadyUpToDate as e: except errors.ImageAlreadyUpToDate as e:
click.echo(f"{e}") click.echo(f"{e}")
except errors.InvalidLogIndex as e:
click.echo(f"❌ Trying to install image older that the currently installed one")
raise click.Abort()
except Exception as e:
click.echo(f"{e}")
raise click.Abort() raise click.Abort()

View file

@ -215,9 +215,7 @@ def _get_blob(tmpdir: str, digest: str) -> Path:
return Path(tmpdir) / "blobs" / "sha256" / digest.replace("sha256:", "") return Path(tmpdir) / "blobs" / "sha256" / digest.replace("sha256:", "")
def upgrade_container_image_airgapped( def upgrade_container_image_airgapped(container_tar: str, pubkey: str) -> str:
container_tar: str, pubkey: str, bypass_logindex: bool = False
) -> str:
""" """
Verify the given archive against its self-contained signatures, then Verify the given archive against its self-contained signatures, then
upgrade the image and retag it to the expected tag. upgrade the image and retag it to the expected tag.
@ -263,15 +261,14 @@ def upgrade_container_image_airgapped(
image_name, signatures = convert_oci_images_signatures(json.load(f), tmpdir) image_name, signatures = convert_oci_images_signatures(json.load(f), tmpdir)
log.info(f"Found image name: {image_name}") log.info(f"Found image name: {image_name}")
if not bypass_logindex: # Ensure that we only upgrade if the log index is higher than the last known one
# Ensure that we only upgrade if the log index is higher than the last known one incoming_log_index = get_log_index_from_signatures(signatures)
incoming_log_index = get_log_index_from_signatures(signatures) last_log_index = get_last_log_index()
last_log_index = get_last_log_index()
if incoming_log_index < last_log_index: if incoming_log_index < last_log_index:
raise errors.InvalidLogIndex( raise errors.InvalidLogIndex(
"The log index is not higher than the last known one" "The log index is not higher than the last known one"
) )
image_digest = index_json["manifests"][0].get("digest").replace("sha256:", "") image_digest = index_json["manifests"][0].get("digest").replace("sha256:", "")