-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Sign docker images using github attestations #8685
Conversation
fd48d69
to
5abc4eb
Compare
A word of warning: I am not 100% certain I fully understand everything that the |
cc @samypr100 (as always, no obligation) |
5abc4eb
to
d1a3809
Compare
d1a3809
to
2872b9a
Compare
2872b9a
to
9b162d3
Compare
Note, I'm running a release job on my fork with these changes (9b162d) as I'd like to see it working E2E https://github.com/samypr100/uv/actions/runs/11593512252 |
@mjpieters signed images are here https://github.com/samypr100/uv/pkgs/container/uv in case you'd like to verify the signatures are working as expected |
9b162d3
to
4a278c1
Compare
Excellent! I was working my way through understanding cargo dist in my own fork to try this out but hadn't gotten as far as actually seeing the workflow complete. The first thing I notice is that the the .sig files are now obscuring the actual docker images on that page, which is a bummer. The signatures are valid however!
I'll have to see what can be done about those signature files in the registry. |
So cosign pushes the signature as a new 'container' to the registry, tagged with I've looked at a number of other projects that use cosign to sign their containers (of which there are a very large number), and all the ones I looked at so far show these tags at the top. E.g. the Dependabot update bundler (a Github project!) has signature tags at the top. You see this on other registries too, e.g. the boxyhq jackson container on the docker hub. I see but a few options here:
|
We're already pushing the |
You push not only a tag, but a manifest as well. You'd have to separate the two steps; push the manifest without tags and then tag the digest of the manifest afterwards. It could be that you can retag the same digest; I'll try this out in my own fork registry. |
I think the main issue here is how GH ranks packages and gives no control over the ordering to orgs/users of what's displayed, so we have to rely on these ordering hacks related to publishing. |
and from my experiments it is clear that it is order that the manifest were pushed to the registry that is used to list them. I tried deleting then restoring, and retagging (moving tags to another manifest then back again to the right manifest), and nothing shifts the signature from the top. So the only thing that would work is to build and not push, sign (and let cosign push the signature manifest), and only then push the actual image manifest. |
6dceed9
to
995e461
Compare
995e461
to
1d03cda
Compare
# PRs from forks don't have access to secrets, disable this step in that case. | ||
if: ${{ github.event.pull_request.head.repo.full_name == 'astral-sh/uv' }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added this in here so this workflow would at least build the docker image in this PR. The jobs otherwise would just fail with a Password required error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note, I think there's 3 other places in this file missing this conditional (if we're in favor of adding it)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't think there was any point as those 3 all are part of jobs that only run on release.
1d03cda
to
59afb8e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you! I might wait for @samypr100 to give it a look too.
# PRs from forks don't have access to secrets, disable this step in that case. | ||
if: ${{ github.event.pull_request.head.repo.full_name == 'astral-sh/uv' }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note, I think there's 3 other places in this file missing this conditional (if we're in favor of adding it)
Good news is that this approach does keep the tags working as-is. I tried it on a test run here https://github.com/samypr100/uv/actions/runs/13066181068 Which did keep the package versions tags intact https://github.com/samypr100/uv/pkgs/container/uv Verifications also work! $ gh attestation verify --owner samypr100 oci://ghcr.io/samypr100/uv:latest [23:14:17]
Loaded digest sha256:ebd769519134c730eb1af61ddd06a8f5629f5082d0c2d8f02a6d577fe4b2a9dc for oci://ghcr.io/samypr100/uv:latest
Loaded 1 attestation from GitHub API
✓ Verification succeeded!
sha256:ebd769519134c730eb1af61ddd06a8f5629f5082d0c2d8f02a6d577fe4b2a9dc was attested by:
REPO PREDICATE_TYPE WORKFLOW
samypr100/uv https://slsa.dev/provenance/v1 .github/workflows/build-docker.yml@refs/heads/cosign-docker-images
$ gh attestation verify --owner samypr100 oci://ghcr.io/samypr100/uv:0.5.26 [23:14:23]
Loaded digest sha256:ebd769519134c730eb1af61ddd06a8f5629f5082d0c2d8f02a6d577fe4b2a9dc for oci://ghcr.io/samypr100/uv:0.5.26
Loaded 1 attestation from GitHub API
✓ Verification succeeded!
sha256:ebd769519134c730eb1af61ddd06a8f5629f5082d0c2d8f02a6d577fe4b2a9dc was attested by:
REPO PREDICATE_TYPE WORKFLOW
samypr100/uv https://slsa.dev/provenance/v1 .github/workflows/build-docker.yml@refs/heads/cosign-docker-images
$ gh attestation verify --owner samypr100 oci://ghcr.io/samypr100/uv:0.5 [23:14:27]
Loaded digest sha256:ebd769519134c730eb1af61ddd06a8f5629f5082d0c2d8f02a6d577fe4b2a9dc for oci://ghcr.io/samypr100/uv:0.5
Loaded 1 attestation from GitHub API
✓ Verification succeeded!
sha256:ebd769519134c730eb1af61ddd06a8f5629f5082d0c2d8f02a6d577fe4b2a9dc was attested by:
REPO PREDICATE_TYPE WORKFLOW
samypr100/uv https://slsa.dev/provenance/v1 .github/workflows/build-docker.yml@refs/heads/cosign-docker-images
$ gh attestation verify --owner samypr100 oci://ghcr.io/samypr100/uv:python3.13-bookworm [23:14:41]
Loaded digest sha256:5537896c0c8bd2351350d32dea35c590997c418e954fb5b31d6fcbfd96126562 for oci://ghcr.io/samypr100/uv:python3.13-bookworm
Loaded 1 attestation from GitHub API
✓ Verification succeeded!
sha256:5537896c0c8bd2351350d32dea35c590997c418e954fb5b31d6fcbfd96126562 was attested by:
REPO PREDICATE_TYPE WORKFLOW
samypr100/uv https://slsa.dev/provenance/v1 .github/workflows/build-docker.yml@refs/heads/cosign-docker-images
... |
cosign uses the GitHub action ID token to retrieve an ephemeral code signing certificate from Fulcio, and store the signature in the Rekor transparency log.
59afb8e
to
04398a4
Compare
Would you mind following with a brief guide on how to verify images in https://docs.astral.sh/uv/guides/integration/docker/ ? |
I'll see what I can do! |
GitHub attestation signing uses the GitHub action ID token to retrieve an ephemeral code signing certificate from Fulcio, and store the signature in the Rekor transparency log.
Once an image has been successfully signed, you should be able to verify the signature with:
Closes #8670