mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-03-17 20:47:50 +02:00
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 this PR, but since `digest` should be always there (if not, the pipeline will fail way earlier), it should be fine. refs https://github.com/goreleaser/goreleaser/issues/3496 refs https://github.com/goreleaser/goreleaser/pull/3540 Signed-off-by: Carlos A Becker <caarlos0@users.noreply.github.com>
This commit is contained in:
parent
2a46d627c7
commit
b55b9976c7
@ -137,6 +137,7 @@ const (
|
||||
ExtraBinaries = "Binaries"
|
||||
ExtraRefresh = "Refresh"
|
||||
ExtraReplaces = "Replaces"
|
||||
ExtraDigest = "Digest"
|
||||
)
|
||||
|
||||
// Extras represents the extra fields in an artifact.
|
||||
|
@ -20,7 +20,7 @@ import (
|
||||
|
||||
const (
|
||||
dockerConfigExtra = "DockerConfig"
|
||||
dockerDigestExtra = "Digest"
|
||||
dockerDigestExtra = artifact.ExtraDigest
|
||||
|
||||
useBuildx = "buildx"
|
||||
useDocker = "docker"
|
||||
|
@ -154,6 +154,7 @@ func signone(ctx *context.Context, cfg config.Sign, art *artifact.Artifact) ([]*
|
||||
env["artifactName"] = art.Name // shouldn't be used
|
||||
env["artifact"] = art.Path
|
||||
env["artifactID"] = art.ID()
|
||||
env["digest"] = artifact.ExtraOr(*art, artifact.ExtraDigest, "")
|
||||
|
||||
tmplEnv, err := templateEnvS(ctx, cfg.Env)
|
||||
if err != nil {
|
||||
|
@ -28,7 +28,7 @@ func (DockerPipe) Default(ctx *context.Context) error {
|
||||
cfg.Cmd = "cosign"
|
||||
}
|
||||
if len(cfg.Args) == 0 {
|
||||
cfg.Args = []string{"sign", "--key=cosign.key", "$artifact"}
|
||||
cfg.Args = []string{"sign", "--key=cosign.key", "${artifact}@${digest}"}
|
||||
}
|
||||
if cfg.Artifacts == "" {
|
||||
cfg.Artifacts = "none"
|
||||
|
@ -28,7 +28,7 @@ func TestDockerSignDefault(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, ctx.Config.DockerSigns[0].Cmd, "cosign")
|
||||
require.Equal(t, ctx.Config.DockerSigns[0].Signature, "")
|
||||
require.Equal(t, ctx.Config.DockerSigns[0].Args, []string{"sign", "--key=cosign.key", "$artifact"})
|
||||
require.Equal(t, ctx.Config.DockerSigns[0].Args, []string{"sign", "--key=cosign.key", "${artifact}@${digest}"})
|
||||
require.Equal(t, ctx.Config.DockerSigns[0].Artifacts, "none")
|
||||
}
|
||||
|
||||
@ -54,12 +54,15 @@ func TestDockerSignArtifacts(t *testing.T) {
|
||||
testlib.CheckPath(t, "cosign")
|
||||
key := "cosign.key"
|
||||
cmd := "sh"
|
||||
args := []string{"-c", "echo ${artifact} > ${signature} && cosign sign --key=" + key + " --upload=false ${artifact} > ${signature}"}
|
||||
args := []string{"-c", "echo ${artifact}@${digest} > ${signature} && cosign sign --key=" + key + " --upload=false ${artifact}@${digest} > ${signature}"}
|
||||
password := "password"
|
||||
|
||||
img1 := "ghcr.io/caarlos0/goreleaser-docker-manifest-actions-example:1.2.1-amd64"
|
||||
img1Digest := "sha256:d7bf8be1b156cc0cd9d2e33765a69bc968d4ef6b2dea9b207d63129b9709862a"
|
||||
img2 := "ghcr.io/caarlos0/goreleaser-docker-manifest-actions-example:1.2.1-arm64v8"
|
||||
img2Digest := "sha256:551801b7f42f8c33bfabb06e25804c2aca14776d2b7df33e07de54e887910b72"
|
||||
man1 := "ghcr.io/caarlos0/goreleaser-docker-manifest-actions-example:1.2.1"
|
||||
man1Digest := "sha256:b5db21408555f1ef5d68008a0a03a7caba3f29b62c64f1404e139b005a20bf03"
|
||||
|
||||
for name, cfg := range map[string]struct {
|
||||
Signs []config.Sign
|
||||
@ -88,7 +91,7 @@ func TestDockerSignArtifacts(t *testing.T) {
|
||||
Stdin: &password,
|
||||
Cmd: "cosign",
|
||||
Certificate: `{{ replace (replace (replace .Env.artifact "/" "-") ":" "-") "." "" }}.pem`,
|
||||
Args: []string{"sign", "--output-certificate=${certificate}", "--key=" + key, "--upload=false", "${artifact}"},
|
||||
Args: []string{"sign", "--output-certificate=${certificate}", "--key=" + key, "--upload=false", "${artifact}@${digest}"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -165,7 +168,8 @@ func TestDockerSignArtifacts(t *testing.T) {
|
||||
Path: img1,
|
||||
Type: artifact.DockerImage,
|
||||
Extra: map[string]interface{}{
|
||||
artifact.ExtraID: "img1",
|
||||
artifact.ExtraID: "img1",
|
||||
artifact.ExtraDigest: img1Digest,
|
||||
},
|
||||
})
|
||||
ctx.Artifacts.Add(&artifact.Artifact{
|
||||
@ -173,7 +177,8 @@ func TestDockerSignArtifacts(t *testing.T) {
|
||||
Path: img2,
|
||||
Type: artifact.DockerImage,
|
||||
Extra: map[string]interface{}{
|
||||
artifact.ExtraID: "img2",
|
||||
artifact.ExtraID: "img2",
|
||||
artifact.ExtraDigest: img2Digest,
|
||||
},
|
||||
})
|
||||
ctx.Artifacts.Add(&artifact.Artifact{
|
||||
@ -181,7 +186,8 @@ func TestDockerSignArtifacts(t *testing.T) {
|
||||
Path: man1,
|
||||
Type: artifact.DockerManifest,
|
||||
Extra: map[string]interface{}{
|
||||
artifact.ExtraID: "man1",
|
||||
artifact.ExtraID: "man1",
|
||||
artifact.ExtraDigest: man1Digest,
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -28,7 +28,7 @@ docker_signs:
|
||||
|
||||
# Command line templateable arguments for the command
|
||||
#
|
||||
# defaults to `["sign", "--key=cosign.key", "${artifact}"]`
|
||||
# defaults to `["sign", "--key=cosign.key", "${artifact}@${digest}"]`
|
||||
args: ["sign", "--key=cosign.key", "--upload=false", "${artifact}"]
|
||||
|
||||
|
||||
@ -77,12 +77,16 @@ docker_signs:
|
||||
These environment variables might be available in the fields that are templateable:
|
||||
|
||||
- `${artifact}`: the path to the artifact that will be signed [^1]
|
||||
- `${digest}`: the digest of the image/manifest that will be signed [^2]
|
||||
- `${artifactID}`: the ID of the artifact that will be signed
|
||||
- `${certificate}`: the certificate file name, if provided
|
||||
|
||||
[^1]: notice that this might contain `/` characters, which depending on how
|
||||
you use it might evaluate to actual paths within the file system. Use with
|
||||
care.
|
||||
[^2]: those are extracted automatically when running Docker push from within
|
||||
GoReleaser. Using the digest helps making sure you're signing the right image
|
||||
and avoid concurrency issues.
|
||||
|
||||
|
||||
## Common usage example
|
||||
|
Loading…
x
Reference in New Issue
Block a user