github.com/goreleaser/goreleaser@v1.25.1/internal/pipe/sign/sign_docker_test.go (about) 1 package sign 2 3 import ( 4 "os" 5 "path/filepath" 6 "strings" 7 "testing" 8 9 "github.com/goreleaser/goreleaser/internal/artifact" 10 "github.com/goreleaser/goreleaser/internal/gio" 11 "github.com/goreleaser/goreleaser/internal/skips" 12 "github.com/goreleaser/goreleaser/internal/testctx" 13 "github.com/goreleaser/goreleaser/internal/testlib" 14 "github.com/goreleaser/goreleaser/pkg/config" 15 "github.com/stretchr/testify/require" 16 ) 17 18 func TestDockerSignDescription(t *testing.T) { 19 require.NotEmpty(t, DockerPipe{}.String()) 20 } 21 22 func TestDockerSignDefault(t *testing.T) { 23 ctx := testctx.NewWithCfg(config.Project{ 24 DockerSigns: []config.Sign{{}}, 25 }) 26 err := DockerPipe{}.Default(ctx) 27 require.NoError(t, err) 28 require.Equal(t, "cosign", ctx.Config.DockerSigns[0].Cmd) 29 require.Equal(t, "", ctx.Config.DockerSigns[0].Signature) 30 require.Equal(t, []string{"sign", "--key=cosign.key", "${artifact}@${digest}", "--yes"}, ctx.Config.DockerSigns[0].Args) 31 require.Equal(t, "none", ctx.Config.DockerSigns[0].Artifacts) 32 } 33 34 func TestDockerSignDisabled(t *testing.T) { 35 ctx := testctx.NewWithCfg(config.Project{ 36 DockerSigns: []config.Sign{ 37 {Artifacts: "none"}, 38 }, 39 }) 40 err := DockerPipe{}.Publish(ctx) 41 require.EqualError(t, err, "artifact signing is disabled") 42 } 43 44 func TestDockerSignInvalidArtifacts(t *testing.T) { 45 ctx := testctx.NewWithCfg(config.Project{ 46 DockerSigns: []config.Sign{ 47 {Artifacts: "foo"}, 48 }, 49 }) 50 err := DockerPipe{}.Publish(ctx) 51 require.EqualError(t, err, "invalid list of artifacts to sign: foo") 52 } 53 54 func TestDockerSignArtifacts(t *testing.T) { 55 testlib.CheckPath(t, "cosign") 56 key := "cosign.key" 57 cmd := "sh" 58 args := []string{"-c", "echo ${artifact}@${digest} > ${signature} && cosign sign --key=" + key + " --upload=false ${artifact}@${digest} --yes > ${signature}"} 59 password := "password" 60 61 img1 := "ghcr.io/caarlos0/goreleaser-docker-manifest-actions-example:1.2.1-amd64" 62 img1Digest := "sha256:d7bf8be1b156cc0cd9d2e33765a69bc968d4ef6b2dea9b207d63129b9709862a" 63 img2 := "ghcr.io/caarlos0/goreleaser-docker-manifest-actions-example:1.2.1-arm64v8" 64 img2Digest := "sha256:551801b7f42f8c33bfabb06e25804c2aca14776d2b7df33e07de54e887910b72" 65 man1 := "ghcr.io/caarlos0/goreleaser-docker-manifest-actions-example:1.2.1" 66 man1Digest := "sha256:b5db21408555f1ef5d68008a0a03a7caba3f29b62c64f1404e139b005a20bf03" 67 68 for name, cfg := range map[string]struct { 69 Signs []config.Sign 70 Expected []string 71 }{ 72 "no signature file": { 73 Expected: nil, // no sigs 74 Signs: []config.Sign{ 75 { 76 Artifacts: "all", 77 Stdin: &password, 78 Cmd: "cosign", 79 Args: []string{"sign", "--key=" + key, "--upload=false", "${artifact}", "--yes"}, 80 }, 81 }, 82 }, 83 "only certificate": { 84 Expected: []string{ 85 "ghcrio-caarlos0-goreleaser-docker-manifest-actions-example-121-amd64.pem", 86 "ghcrio-caarlos0-goreleaser-docker-manifest-actions-example-121-arm64v8.pem", 87 "ghcrio-caarlos0-goreleaser-docker-manifest-actions-example-121.pem", 88 }, 89 Signs: []config.Sign{ 90 { 91 Artifacts: "all", 92 Stdin: &password, 93 Cmd: "cosign", 94 Certificate: `{{ replace (replace (replace .Env.artifact "/" "-") ":" "-") "." "" }}.pem`, 95 Args: []string{"sign", "--output-certificate=${certificate}", "--key=" + key, "--upload=false", "${artifact}@${digest}", "--yes"}, 96 }, 97 }, 98 }, 99 "sign all": { 100 Expected: []string{ 101 "all_img1.sig", 102 "all_img2.sig", 103 "all_man1.sig", 104 }, 105 Signs: []config.Sign{ 106 { 107 Artifacts: "all", 108 Stdin: &password, 109 Signature: `all_${artifactID}.sig`, 110 Cmd: cmd, 111 Args: args, 112 }, 113 }, 114 }, 115 "sign all filtering id": { 116 Expected: []string{"all_filter_by_id_img2.sig"}, 117 Signs: []config.Sign{ 118 { 119 Artifacts: "all", 120 IDs: []string{"img2"}, 121 Stdin: &password, 122 Signature: "all_filter_by_id_${artifactID}.sig", 123 Cmd: cmd, 124 Args: args, 125 }, 126 }, 127 }, 128 "sign images only": { 129 Expected: []string{ 130 "images_img1.sig", 131 "images_img2.sig", 132 }, 133 Signs: []config.Sign{ 134 { 135 Artifacts: "images", 136 Stdin: &password, 137 Signature: "images_${artifactID}.sig", 138 Cmd: cmd, 139 Args: args, 140 }, 141 }, 142 }, 143 "sign manifests only": { 144 Expected: []string{"manifests_man1.sig"}, 145 Signs: []config.Sign{ 146 { 147 Artifacts: "manifests", 148 Stdin: &password, 149 Signature: "manifests_${artifactID}.sig", 150 Cmd: cmd, 151 Args: args, 152 }, 153 }, 154 }, 155 // TODO: keyless test? 156 } { 157 t.Run(name, func(t *testing.T) { 158 ctx := testctx.NewWithCfg(config.Project{ 159 DockerSigns: cfg.Signs, 160 }) 161 wd, err := os.Getwd() 162 require.NoError(t, err) 163 tmp := testlib.Mktmp(t) 164 require.NoError(t, gio.Copy(filepath.Join(wd, "testdata/cosign/"), tmp)) 165 ctx.Config.Dist = "dist" 166 require.NoError(t, os.Mkdir("dist", 0o755)) 167 168 ctx.Artifacts.Add(&artifact.Artifact{ 169 Name: img1, 170 Path: img1, 171 Type: artifact.DockerImage, 172 Extra: map[string]interface{}{ 173 artifact.ExtraID: "img1", 174 artifact.ExtraDigest: img1Digest, 175 }, 176 }) 177 ctx.Artifacts.Add(&artifact.Artifact{ 178 Name: img2, 179 Path: img2, 180 Type: artifact.DockerImage, 181 Extra: map[string]interface{}{ 182 artifact.ExtraID: "img2", 183 artifact.ExtraDigest: img2Digest, 184 }, 185 }) 186 ctx.Artifacts.Add(&artifact.Artifact{ 187 Name: man1, 188 Path: man1, 189 Type: artifact.DockerManifest, 190 Extra: map[string]interface{}{ 191 artifact.ExtraID: "man1", 192 artifact.ExtraDigest: man1Digest, 193 }, 194 }) 195 196 require.NoError(t, DockerPipe{}.Default(ctx)) 197 require.NoError(t, DockerPipe{}.Publish(ctx)) 198 var sigs []string 199 for _, sig := range ctx.Artifacts.Filter( 200 artifact.Or( 201 artifact.ByType(artifact.Signature), 202 artifact.ByType(artifact.Certificate), 203 ), 204 ).List() { 205 sigs = append(sigs, sig.Name) 206 require.Truef(t, strings.HasPrefix(sig.Path, ctx.Config.Dist), "signature %q is not in dist dir %q", sig.Path, ctx.Config.Dist) 207 } 208 require.Equal(t, cfg.Expected, sigs) 209 }) 210 } 211 } 212 213 func TestDockerSkip(t *testing.T) { 214 t.Run("skip", func(t *testing.T) { 215 require.True(t, DockerPipe{}.Skip(testctx.New())) 216 }) 217 218 t.Run("skip sign", func(t *testing.T) { 219 ctx := testctx.New(testctx.Skip(skips.Sign)) 220 require.True(t, DockerPipe{}.Skip(ctx)) 221 }) 222 223 t.Run("dont skip", func(t *testing.T) { 224 ctx := testctx.NewWithCfg(config.Project{ 225 DockerSigns: []config.Sign{ 226 {}, 227 }, 228 }) 229 require.False(t, DockerPipe{}.Skip(ctx)) 230 }) 231 } 232 233 func TestDockerDependencies(t *testing.T) { 234 ctx := testctx.NewWithCfg(config.Project{ 235 DockerSigns: []config.Sign{ 236 {Cmd: "cosign"}, 237 {Cmd: "gpg2"}, 238 }, 239 }) 240 require.Equal(t, []string{"cosign", "gpg2"}, DockerPipe{}.Dependencies(ctx)) 241 }