github.com/szyn/goreleaser@v0.76.1-0.20180517112710-333da09a1297/pipeline/sign/sign_test.go (about) 1 package sign 2 3 import ( 4 "bytes" 5 "io/ioutil" 6 "os" 7 "os/exec" 8 "path/filepath" 9 "sort" 10 "testing" 11 12 "github.com/goreleaser/goreleaser/config" 13 "github.com/goreleaser/goreleaser/context" 14 "github.com/goreleaser/goreleaser/internal/artifact" 15 "github.com/stretchr/testify/assert" 16 ) 17 18 func TestDescription(t *testing.T) { 19 assert.NotEmpty(t, Pipe{}.String()) 20 } 21 22 func TestSignDefault(t *testing.T) { 23 ctx := &context.Context{} 24 Pipe{}.Default(ctx) 25 assert.Equal(t, ctx.Config.Sign.Cmd, "gpg") 26 assert.Equal(t, ctx.Config.Sign.Signature, "${artifact}.sig") 27 assert.Equal(t, ctx.Config.Sign.Args, []string{"--output", "$signature", "--detach-sig", "$artifact"}) 28 assert.Equal(t, ctx.Config.Sign.Artifacts, "none") 29 } 30 31 func TestSignDisabled(t *testing.T) { 32 ctx := &context.Context{} 33 ctx.Config.Sign.Artifacts = "none" 34 err := Pipe{}.Run(ctx) 35 assert.EqualError(t, err, "artifact signing disabled") 36 } 37 38 func TestSignInvalidArtifacts(t *testing.T) { 39 ctx := &context.Context{} 40 ctx.Config.Sign.Artifacts = "foo" 41 err := Pipe{}.Run(ctx) 42 assert.EqualError(t, err, "invalid list of artifacts to sign: foo") 43 } 44 45 func TestSignArtifacts(t *testing.T) { 46 // fix permission on keyring dir to suppress warning about insecure permissions 47 assert.NoError(t, os.Chmod(keyring, 0700)) 48 49 tests := []struct { 50 desc string 51 ctx *context.Context 52 signatures []string 53 }{ 54 { 55 desc: "sign all artifacts", 56 ctx: context.New( 57 config.Project{ 58 Sign: config.Sign{Artifacts: "all"}, 59 }, 60 ), 61 signatures: []string{"artifact1.sig", "artifact2.sig", "checksum.sig"}, 62 }, 63 { 64 desc: "sign only checksums", 65 ctx: context.New( 66 config.Project{ 67 Sign: config.Sign{Artifacts: "checksum"}, 68 }, 69 ), 70 signatures: []string{"checksum.sig"}, 71 }, 72 } 73 74 for _, tt := range tests { 75 t.Run(tt.desc, func(t *testing.T) { 76 testSign(t, tt.ctx, tt.signatures) 77 }) 78 } 79 } 80 81 const keyring = "testdata/gnupg" 82 const user = "nopass" 83 84 func testSign(t *testing.T, ctx *context.Context, signatures []string) { 85 // create temp dir for file and signature 86 tmpdir, err := ioutil.TempDir("", "goreleaser") 87 assert.NoError(t, err) 88 defer os.RemoveAll(tmpdir) 89 90 ctx.Config.Dist = tmpdir 91 92 // create some fake artifacts 93 var artifacts = []string{"artifact1", "artifact2", "checksum"} 94 for _, f := range artifacts { 95 file := filepath.Join(tmpdir, f) 96 assert.NoError(t, ioutil.WriteFile(file, []byte("foo"), 0644)) 97 } 98 ctx.Artifacts.Add(artifact.Artifact{ 99 Name: "artifact1", 100 Path: filepath.Join(tmpdir, "artifact1"), 101 Type: artifact.UploadableArchive, 102 }) 103 ctx.Artifacts.Add(artifact.Artifact{ 104 Name: "artifact2", 105 Path: filepath.Join(tmpdir, "artifact2"), 106 Type: artifact.UploadableArchive, 107 }) 108 ctx.Artifacts.Add(artifact.Artifact{ 109 Name: "checksum", 110 Path: filepath.Join(tmpdir, "checksum"), 111 Type: artifact.Checksum, 112 }) 113 114 // configure the pipeline 115 // make sure we are using the test keyring 116 assert.NoError(t, Pipe{}.Default(ctx)) 117 ctx.Config.Sign.Args = append([]string{"--homedir", keyring}, ctx.Config.Sign.Args...) 118 119 // run the pipeline 120 assert.NoError(t, Pipe{}.Run(ctx)) 121 122 // verify that only the artifacts and the signatures are in the dist dir 123 files, err := ioutil.ReadDir(tmpdir) 124 assert.NoError(t, err) 125 gotFiles := []string{} 126 for _, f := range files { 127 gotFiles = append(gotFiles, f.Name()) 128 } 129 wantFiles := append(artifacts, signatures...) 130 sort.Strings(wantFiles) 131 assert.Equal(t, wantFiles, gotFiles) 132 133 // verify the signatures 134 for _, sig := range signatures { 135 verifySignature(t, ctx, sig) 136 } 137 138 var signArtifacts []string 139 for _, sig := range ctx.Artifacts.Filter(artifact.ByType(artifact.Signature)).List() { 140 signArtifacts = append(signArtifacts, sig.Name) 141 } 142 // check signature is an artifact 143 assert.Equal(t, signArtifacts, signatures) 144 } 145 146 func verifySignature(t *testing.T, ctx *context.Context, sig string) { 147 artifact := sig[:len(sig)-len(".sig")] 148 149 // verify signature was made with key for usesr 'nopass' 150 cmd := exec.Command("gpg", "--homedir", keyring, "--verify", filepath.Join(ctx.Config.Dist, sig), filepath.Join(ctx.Config.Dist, artifact)) 151 out, err := cmd.CombinedOutput() 152 assert.NoError(t, err) 153 154 // check if the signature matches the user we expect to do this properly we 155 // might need to have either separate keyrings or export the key from the 156 // keyring before we do the verification. For now we punt and look in the 157 // output. 158 if !bytes.Contains(out, []byte(user)) { 159 t.Fatalf("signature is not from %s", user) 160 } 161 }