Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement independent container updates #1006

Open
harrislapiroff opened this issue Nov 21, 2024 · 0 comments
Open

Implement independent container updates #1006

harrislapiroff opened this issue Nov 21, 2024 · 0 comments
Labels
icu Issues related with independent container updates
Milestone

Comments

@harrislapiroff
Copy link

harrislapiroff commented Nov 21, 2024

Dangerzone currently relies on a container image to do the conversion work. This image is shipped as part of the application packages (.msi .dmg, .rpm, .deb files, depending on the platform).

This has a few disadvantages:

  1. There is no way to update the image unless we issue a new release. This is problematic because:
    1. It makes us issue new releases "just" to upgrade the security of the container ;
    2. The image can get out of date, and have security breaches. Old versions are still installable, but they contain an un-patched container image ;
  2. Including the images inside the packages inflates their size ;
  3. Having images included in the packages doesn't comply with the Debian policy, making it a roadblock for inclusion in upstream Debian.

Rather than including the images in the application packages, they will be published to a registry, and dangerzone will be checking for new images as part of its update mechanism (only if enabled by the client - opt in).

Note

Slim Versions

We are thinking about having two different kind of versions:

  • "Full" versions, which will contain the original container image ; and
  • "Slim" versions, containing everything except the container image itself

(thanks Ethan for the idea)

Overview

Here a general high level overview how what will be done:

Releaser standpoint:

  • Container images will be built nightly by Github Actions, and published to the GitHub Container Registry (abbreviated to "ghcr" for the rest of this text).

    • Attestations will be attached to the ghcr (see Implement container image attestations #1035 for details)
    • They will not be tagged as latest by default. Their tag will have a format like YYYYMMDD-<version>-g<commit>, e.g., 20241219-0.8.0-77-g06a9117.
    • Achieving SLSA level 3 is trivially possible (link). In practice, we can't rely on just SLSA 3, but it's a good to have.
  • When we would like to update the container image, we will:

    • Get the hash of the container image we want to ship ;
    • Hop on our signer machines, and build the image by our own means.
    • Check that the produced image matches the one published in the nightlies (see the section on reproducible builds for more info)
    • Verify attestations, checking for the provenance of the image.
    • Sign the container image and tag it to be the latest one in the ghcr (see Sign container images #1036 for details). While doing so, the previous attestations will remain there, and have a signature on top. This will make it available for download.
      • We can sign the container image using our YubiKeys, as we already do for releases.

Client standpoint:

  • In addition to checking for new "releases" (see design doc), check if new images are available, either by looking GitHub's Package API (docs), or directly GitHub's container registry API.
  • When a new image is available tagged as latest, check its signature against a known key (embedded in the application package)
  • Download the new image using {docker,podman} pull
  • (Optional ?) Verify that the image has been built by GitHub, for our organization and from a specified workflow. This double verification will help in the (admittedly catastrophic) scenario where our HSM becomes compromised.

Reproducible Builds

Because we don't want to put too much trust in the Github Container Registry (and in general in the Microsoft Github ecosystem), having reproducible containers is important for us.

With reproducible builds, it's possible to ensure that a local build of a container image is the same as one built on a different infrastructure. For Dangerzone, reproducibility is currently implemented in a WIP branch, as part of this « Independent Container Updates ».

Note

It's not easy to check that the image digests match due to different file timestamps. However, we can use diffoci in order to check everything else (file contents, permissions) and ignore timestamps.

See #188 for details on the matter.

Interaction with Container Registries

In order to either publish data to the container registry or retrieve information, we might want to use a tool to do that for us.

Container registries follow the Manifest v2 specification, and as such client side tools exist. We quickly wrote a simple script (that needs some more information) able to download following the Cosign Bundle Spec. It's not clear yet if we should write something or if something already exist in python to do that for us.

Tool comparison

We are currently not sure which tool we should use to verify signatures and attestations. There is an array of options available. Here is a summary of their capabilities:

Name Create attestations¹ Verify attestations¹ Apply signatures² Verify signatures² Library?
cosign ✖ ³ Partially ³
sigstore-go
sigstore-python Partially ⁴ Partially ⁴
gh cli

* Size before compression
¹ Following the Cosign Bundle Spec
² Following the Cosign Signature Spec
³ At the time of writing, cosign doesn't embed a way to verify the attestations produced by the Cosign Bundle Spec. without tools to interact with the container registry on the side. As such a small gymnastic is currently required. It's possible to track the progress on this effort here.
sigstore-python provides ways to sign attestations using a DSSE, but doesn't include ways to interact with container registries

  • A rust library also exists (sigstore-rs) but we kept it out because it's described as "under active development and will not be considered stable until the 1.0 release." I'll add a note about it.

Future work

Keyless signing

Sigstore provides a way to sign without using keys, that they call "Keyless Signing". This builds on top of OIDC providers (think GitHub or Microsoft accounts), and does the following:

  1. Login to an OIDC provider
  2. Generate a key pair from it:
    • privKey: temporary signing key, that never hits the disk
    • pubKey: derived from the public key
  3. Apply the signature
  4. Publish the pubKey to the certificate transparency log

We might want to use keyless signing in the future, where images could be signed by multiple identities.

These identities could be defined at the time of the release, effectively embedding the trust model in the published package. For instance, we could embed a rule stating that container updates should be coming from either apyrgio@github or almet@github.


Edit: added issue content (@almet)
Edit 2: clarified the fact we're adding signatures on top of attestations, and that we are not using HSMs

@harrislapiroff harrislapiroff added this to the 0.9.0 milestone Nov 21, 2024
@apyrgio apyrgio added the icu Issues related with independent container updates label Dec 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
icu Issues related with independent container updates
Projects
Status: Todo
Development

No branches or pull requests

2 participants