1
0
mirror of https://github.com/goreleaser/goreleaser.git synced 2025-07-17 01:42:37 +02:00

feat: blob kms support (#1056)

* feat: blob kms support

Signed-off-by: Carlos Alexandro Becker <caarlos0@gmail.com>

* fix: tests

Signed-off-by: Carlos Alexandro Becker <caarlos0@gmail.com>
This commit is contained in:
Carlos Alexandro Becker
2019-07-12 10:10:22 -03:00
committed by GitHub
parent 00cba17696
commit 4541fd9f20
5 changed files with 73 additions and 41 deletions

9
go.sum
View File

@ -4,6 +4,7 @@ cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7h
cloud.google.com/go v0.39.0 h1:UgQP9na6OTfp4dsAiz/eFpFA1C6tPdH5wiRdi19tuMw=
cloud.google.com/go v0.39.0/go.mod h1:rVLT6fkc8chs9sfPtFc1SBH6em7n+ZoXaG+87tDISts=
contrib.go.opencensus.io/exporter/aws v0.0.0-20181029163544-2befc13012d0/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA=
contrib.go.opencensus.io/exporter/ocagent v0.4.12 h1:jGFvw3l57ViIVEPKKEUXPcLYIXJmQxLUh6ey1eJhwyc=
contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA=
contrib.go.opencensus.io/exporter/stackdriver v0.11.0/go.mod h1:hA7rlmtavV03FGxzWXAPBUnZeZBhWN/QYQAuMtxc9Bk=
contrib.go.opencensus.io/integrations/ocsql v0.1.4/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE=
@ -14,13 +15,16 @@ github.com/Azure/azure-pipeline-go v0.1.8/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9a
github.com/Azure/azure-pipeline-go v0.1.9 h1:u7JFb9fFTE6Y/j8ae2VK33ePrRqJqoCM/IWkQdAZ+rg=
github.com/Azure/azure-pipeline-go v0.1.9/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg=
github.com/Azure/azure-sdk-for-go v21.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v27.3.0+incompatible h1:i+ROfG3CsZUPoVAnhK06T3R6PmBzKB9ds+lHBpN7Mzo=
github.com/Azure/azure-sdk-for-go v27.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-service-bus-go v0.4.1/go.mod h1:d9ho9e/06euiTwGpKxmlbpPhFUsfCsq6a4tZ68r51qI=
github.com/Azure/azure-storage-blob-go v0.6.0 h1:SEATKb3LIHcaSIX+E6/K4kJpwfuozFEsmt5rS56N6CE=
github.com/Azure/azure-storage-blob-go v0.6.0/go.mod h1:oGfmITT1V6x//CswqY2gtAHND+xIP64/qL7a5QJix0Y=
github.com/Azure/go-autorest v11.0.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest v11.1.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest v11.1.2+incompatible h1:viZ3tV5l4gE2Sw0xrasFHytCGtzYCrT+um/rrSQ1BfA=
github.com/Azure/go-autorest v11.1.2+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/tracing v0.1.0 h1:TRBxC5Pj/fIuh4Qob0ZpkggbfT8RC0SubHbpV3p4/Vc=
github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvdeRAgDr0izn4z5Ij88=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20190418212003-6ac0b49e7197/go.mod h1:aJ4qN3TfrelA6NZ6AXsXRfmEVaYin3EDbSPJrKS8OXo=
@ -48,13 +52,16 @@ github.com/caarlos0/ctrlc v1.0.0 h1:2DtF8GSIcajgffDFJzyG15vO+1PuBWOMUdFut7NnXhw=
github.com/caarlos0/ctrlc v1.0.0/go.mod h1:CdXpj4rmq0q/1Eb44M9zi2nKB0QraNKuRGYGrrHhcQw=
github.com/campoy/unique v0.0.0-20180121183637-88950e537e7e h1:V9a67dfYqPLAvzk5hMQOXYJlZ4SLIXgyKIE+ZiHzgGQ=
github.com/campoy/unique v0.0.0-20180121183637-88950e537e7e/go.mod h1:9IOqJGCPMSc6E5ydlp5NIonxObaeu/Iub/X03EKPVYo=
github.com/census-instrumentation/opencensus-proto v0.2.0 h1:LzQXZOgg4CQfE6bFvXGM30YZL1WW/M337pXml+GrcZ4=
github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dimchansky/utfbom v1.1.0 h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TRo4=
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
@ -105,6 +112,7 @@ github.com/goreleaser/nfpm v0.12.0 h1:2eyO5y6SlnokPZIJN98ewVN45ch0j70WenFE9qWyJp
github.com/goreleaser/nfpm v0.12.0/go.mod h1:F2yzin6cBAL9gb+mSiReuXdsfTrOQwDMsuSpULof+y4=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/grpc-ecosystem/grpc-gateway v1.8.5 h1:2+KSC78XiO6Qy0hIjfc1OD9H+hsaJdJlb8Kqsd41CTE=
github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
@ -191,6 +199,7 @@ gocloud.dev v0.15.0/go.mod h1:ShXCyJaGrJu9y/7a6+DSCyBb9MFGZ1P5wwPa0Wu6w34=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181001203147-e3636079e1a4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190422183909-d864b10871cd h1:sMHc2rZHuzQmrbVoSpt9HgerkXPyIeCSO6k0zUMGfFk=
golang.org/x/crypto v0.0.0-20190422183909-d864b10871cd/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=

View File

@ -9,11 +9,6 @@ import (
"github.com/goreleaser/goreleaser/internal/semerrgroup"
"github.com/goreleaser/goreleaser/internal/tmpl"
"github.com/goreleaser/goreleaser/pkg/context"
// Import the blob packages we want to be able to open.
_ "gocloud.dev/blob/azureblob"
_ "gocloud.dev/blob/gcsblob"
_ "gocloud.dev/blob/s3blob"
)
// Pipe for Artifactory

View File

@ -4,6 +4,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"
"github.com/goreleaser/goreleaser/internal/artifact"
@ -219,7 +220,7 @@ func TestPipe_Publish(t *testing.T) {
setEnv(tt.env)
defer unsetEnv(tt.env)
if err := p.Publish(tt.args.ctx); (err != nil) != tt.wantErr {
if err.Error() != tt.wantErrString {
if !strings.HasPrefix(err.Error(), tt.wantErrString) {
t.Errorf("Pipe.Publish() error = %v, wantErr %v", err, tt.wantErrString)
}
}

View File

@ -10,23 +10,30 @@ import (
"github.com/goreleaser/goreleaser/internal/semerrgroup"
"github.com/goreleaser/goreleaser/pkg/config"
"github.com/goreleaser/goreleaser/pkg/context"
gocdk "gocloud.dev/blob"
"github.com/pkg/errors"
"gocloud.dev/blob"
"gocloud.dev/secrets"
// Import the blob packages we want to be able to open.
_ "gocloud.dev/blob/azureblob"
_ "gocloud.dev/blob/gcsblob"
_ "gocloud.dev/blob/s3blob"
// import the secrets packages we want to be able to open:
_ "gocloud.dev/secrets/awskms"
_ "gocloud.dev/secrets/azurekeyvault"
_ "gocloud.dev/secrets/gcpkms"
)
// OpenBucket is the interface that wraps the BucketConnect and UploadBucket method
type OpenBucket interface {
Connect(ctx *context.Context, bucketURL string) (*gocdk.Bucket, error)
Connect(ctx *context.Context, bucketURL string) (*blob.Bucket, error)
Upload(ctx *context.Context, conf config.Blob, folder string) error
}
// Bucket is object which holds connection for Go Bucker Provider
type Bucket struct {
BucketConn *gocdk.Bucket
BucketConn *blob.Bucket
}
// returns openbucket connection for list of providers
@ -35,12 +42,12 @@ func newOpenBucket() OpenBucket {
}
// Connect makes connection with provider
func (b Bucket) Connect(ctx *context.Context, bucketURL string) (*gocdk.Bucket, error) {
bucketConnection, err := gocdk.OpenBucket(ctx, bucketURL)
func (b Bucket) Connect(ctx *context.Context, bucketURL string) (*blob.Bucket, error) {
conn, err := blob.OpenBucket(ctx, bucketURL)
if err != nil {
return nil, err
}
return bucketConnection, nil
return conn, nil
}
// Upload takes connection initilized from newOpenBucket to upload goreleaser artifacts
@ -49,11 +56,11 @@ func (b Bucket) Upload(ctx *context.Context, conf config.Blob, folder string) er
var bucketURL = fmt.Sprintf("%s://%s", conf.Provider, conf.Bucket)
// Get the openbucket connection for specific provider
openbucketConn, err := b.Connect(ctx, bucketURL)
conn, err := b.Connect(ctx, bucketURL)
if err != nil {
return err
}
defer openbucketConn.Close()
defer conn.Close()
var filter = artifact.Or(
artifact.ByType(artifact.UploadableArchive),
@ -70,49 +77,48 @@ func (b Bucket) Upload(ctx *context.Context, conf config.Blob, folder string) er
for _, artifact := range ctx.Artifacts.Filter(filter).List() {
artifact := artifact
g.Go(func() error {
// Prepare artifact for upload.
data, err := ioutil.ReadFile(artifact.Path)
if err != nil {
return err
}
log.WithFields(log.Fields{
"provider": bucketURL,
"artifact": artifact.Name,
}).Info("uploading")
w, err := openbucketConn.NewWriter(ctx, filepath.Join(folder, artifact.Path), nil)
w, err := conn.NewWriter(ctx, filepath.Join(folder, artifact.Path), nil)
if err != nil {
return fmt.Errorf("failed to obtain writer: %s", err)
return errors.Wrap(err, "failed to obtain writer")
}
data, err := getData(ctx, conf, artifact.Path)
if err != nil {
return err
}
_, err = w.Write(data)
if err != nil {
switch {
case errorContains(err, "NoSuchBucket", "ContainerNotFound", "notFound"):
return fmt.Errorf("(%v) provided bucket does not exist", bucketURL)
return errors.Wrapf(err, "provided bucket does not exist: %s", bucketURL)
case errorContains(err, "NoCredentialProviders"):
return fmt.Errorf("check credentials and access to bucket %s", bucketURL)
return errors.Wrapf(err, "check credentials and access to bucket: %s", bucketURL)
default:
return fmt.Errorf("failed to write to bucket : %s", err)
return errors.Wrapf(err, "failed to write to bucket")
}
}
if err = w.Close(); err != nil {
switch {
case errorContains(err, "InvalidAccessKeyId"):
return fmt.Errorf("aws access key id you provided does not exist in our records")
return errors.Wrap(err, "aws access key id you provided does not exist in our records")
case errorContains(err, "AuthenticationFailed"):
return fmt.Errorf("azure storage key you provided is not valid")
return errors.Wrap(err, "azure storage key you provided is not valid")
case errorContains(err, "invalid_grant"):
return fmt.Errorf("google app credentials you provided is not valid")
return errors.Wrap(err, "google app credentials you provided is not valid")
case errorContains(err, "no such host"):
return fmt.Errorf("azure storage account you provided is not valid")
return errors.Wrap(err, "azure storage account you provided is not valid")
case errorContains(err, "NoSuchBucket", "ContainerNotFound", "notFound"):
return fmt.Errorf("(%v) provided bucket does not exist", bucketURL)
return errors.Wrapf(err, "provided bucket does not exist: %s", bucketURL)
case errorContains(err, "NoCredentialProviders"):
return fmt.Errorf("check credentials and access to bucket %s", bucketURL)
return errors.Wrapf(err, "check credentials and access to bucket %s", bucketURL)
case errorContains(err, "ServiceCode=ResourceNotFound"):
return fmt.Errorf("missing azure storage key for provided bucket %s", bucketURL)
return errors.Wrapf(err, "missing azure storage key for provided bucket %s", bucketURL)
default:
return fmt.Errorf("failed to close Bucket writer: %s", err)
return errors.Wrap(err, "failed to close Bucket writer")
}
}
return err
@ -120,3 +126,23 @@ func (b Bucket) Upload(ctx *context.Context, conf config.Blob, folder string) er
}
return g.Wait()
}
func getData(ctx *context.Context, conf config.Blob, path string) ([]byte, error) {
data, err := ioutil.ReadFile(path)
if err != nil {
return data, errors.Wrapf(err, "failed to open file %s", path)
}
if conf.KMSKey == "" {
return data, nil
}
keeper, err := secrets.OpenKeeper(ctx, conf.KMSKey)
if err != nil {
return data, errors.Wrapf(err, "failed to open kms %s", conf.KMSKey)
}
defer keeper.Close()
data, err = keeper.Encrypt(ctx, data)
if err != nil {
return data, errors.Wrap(err, "failed to encrypt with kms")
}
return data, err
}

View File

@ -302,20 +302,21 @@ type Before struct {
// S3 contains s3 config
type S3 struct {
Region string
Bucket string
Folder string
Profile string
Endpoint string // used for minio for example
ACL string
Region string `yaml:",omitempty"`
Bucket string `yaml:",omitempty"`
Folder string `yaml:",omitempty"`
Profile string `yaml:",omitempty"`
Endpoint string `yaml:",omitempty"` // used for minio for example
ACL string `yaml:",omitempty"`
IDs []string `yaml:"ids,omitempty"`
}
// Blob contains config for GO CDK blob
type Blob struct {
Bucket string
Provider string
Folder string
Bucket string `yaml:",omitempty"`
Provider string `yaml:",omitempty"`
Folder string `yaml:",omitempty"`
KMSKey string `yaml:",omitempty"`
IDs []string `yaml:"ids,omitempty"`
}