goreleaser: Built docker image/manifest digest is not exposed to image signing step, leading to potential race condition vulnerability
Is your feature request related to a problem? Please describe.
Currently, the Docker image digest built by dockers: ...
is not exposed to docker_signs: ...
in the environment variables. If the image tag in the registry is modified after pushing and before signing, signer tools that re-pull an image to sign it (including cosign
) will potentially sign an image different from the one that was produced by goreleaser.
Describe the solution you’d like
Docker exposes the --metadata-file
flag to docker build
yields a file that looks like this in the goreleaserdocker
temp dir:
{
"containerimage.digest": "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
}
If we expose this built digest to the docker_signs
tools via an environment variable artifactDigest
, users would have the ability to pass the digest to the signing tool and avoid any chance of a race condition. In my opinion, this should be the default behavior.
docker_signs:
- artifacts: all
cmd: cosign
args: ["sign", "${artifact}@${artifactDigest}"]
Describe alternatives you’ve considered
Assuming you’re using a tool like cosign
that takes an image as an argument, you can fetch the digest from the local Docker daemon and pass that to the signer tool like so:
docker_signs:
- artifacts: all
cmd: sh
args:
- -c
- cosign sign ${artifact}@$(docker inspect ${artifact} -f '{{"{{ (index .RepoDigests 0) }}"}}' | cut -d"@" -f2)
I’m not 100% sure this is actually correct though – docker inspect
returns a list of digests for a given tag, which suggests there may be conditions in which multiple digests are returned for a single tag in the Docker daemon’s image store. I couldn’t find any such case in a quick code search of Docker, however.
This is quite a hack and it should be easier to avoid the race condition.
Search
- I did search for other open and closed issues before opening this.
Code of Conduct
- I agree to follow this project’s Code of Conduct
Additional context
- If cases where users are already passing the
--metadata-file
to thedocker build
command viabuild_flag_templates
, it may not be possible to reliably extract the digest from the docker build. - https://github.com/sigstore/cosign/issues/2047
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 1
- Comments: 17 (10 by maintainers)
Commits related to this issue
- feat: add digest to artifacts info of published docker images (#3540) Extract the digest (sha256) of docker images from the `docker push` command for dockers published to the docker registry. Outpu... — committed to goreleaser/goreleaser by gal-legit 2 years ago
- feat: use digest to sign docker images/manifests (#3556) this drives it home by using the actual images/manifest digests to sign with cosign by default. the default signing command is changing in... — committed to goreleaser/goreleaser by caarlos0 2 years ago
- feat: use digest on manifests (#3555) this use the digests on the manifest creation. Another PR will add it to signing too. refs #3496 refs #3540 Signed-off-by: Carlos A Becker <caarlos0@user... — committed to goreleaser/goreleaser by caarlos0 2 years ago
- refactor: use the variable from artifact refs #3496 Signed-off-by: Carlos A Becker <caarlos0@users.noreply.github.com> — committed to goreleaser/goreleaser by caarlos0 2 years ago
Actually, the digest should be fetched from the output of
docker push
. I demonstrate it in this blog post, which I wrote as a follow-up to my report in SigStore’s Slack channel that led to https://github.com/sigstore/cosign/issues/2047. I checked goreleaser’s code briefly, so I hope I got things right: It seems that the fix takes changing the following function to also fetch stdout and parse it:This would also force fixing the
imager
interface accordingly.