From 6ef9cda6dc5f9319e1fbb7d4c8bbff2252208926 Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Tue, 23 Jun 2020 15:01:17 +0200 Subject: [PATCH 01/37] Add commands to create/list/delete IDP Links --- go.mod | 9 +- go.sum | 23 +-- internals/secrethub/service_gcp.go | 3 + internals/secrethub/service_gcp_link.go | 193 ++++++++++++++++++++++++ 4 files changed, 205 insertions(+), 23 deletions(-) create mode 100644 internals/secrethub/service_gcp_link.go diff --git a/go.mod b/go.mod index a1c0f024..2a4828a5 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,6 @@ require ( bitbucket.org/zombiezen/cardcpx v0.0.0-20150417151802-902f68ff43ef cloud.google.com/go v0.57.0 // indirect github.com/alecthomas/kingpin v1.3.8-0.20200323085623-b6657d9477a6 - github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf github.com/atotto/clipboard v0.1.2 github.com/aws/aws-sdk-go v1.25.49 github.com/docker/go-units v0.3.3 @@ -15,15 +14,17 @@ require ( github.com/mattn/go-colorable v0.1.1 github.com/mattn/go-isatty v0.0.7 github.com/mitchellh/go-homedir v1.1.0 - github.com/mitchellh/mapstructure v1.1.2 github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 + github.com/pkg/errors v0.9.1 // indirect github.com/secrethub/demo-app v0.1.0 - github.com/secrethub/secrethub-go v0.29.0 + github.com/secrethub/secrethub-go v0.29.1-0.20200623115223-14e18aeb8f96 github.com/zalando/go-keyring v0.0.0-20190208082241-fbe81aec3a07 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 + golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d golang.org/x/sys v0.0.0-20200501052902-10377860bb8e golang.org/x/text v0.3.2 google.golang.org/api v0.26.0 - google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect + google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84 gopkg.in/yaml.v2 v2.2.2 + gotest.tools v2.2.0+incompatible ) diff --git a/go.sum b/go.sum index 5db40c7d..b99f9ca5 100644 --- a/go.sum +++ b/go.sum @@ -99,8 +99,6 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -153,21 +151,15 @@ github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQz github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/secrethub/demo-app v0.1.0 h1:HwPPxuiSvx4TBE7Qppzu3A9eHqmsBrIz4Ko8u8pqMqw= github.com/secrethub/demo-app v0.1.0/go.mod h1:ymjm8+WXTSDTFqsGVBNVmHSnwtZMYi7KptHvpo/fLH4= github.com/secrethub/secrethub-cli v0.30.0/go.mod h1:dC0wd40v+iQdV83/0rUrOa01LYq+8Yj2AtJB1vzh2ao= -github.com/secrethub/secrethub-go v0.21.0/go.mod h1:rc2IfKKBJ4L0wGec0u4XnF5/pe0FFPE4Q1MWfrFso7s= -github.com/secrethub/secrethub-go v0.27.1-0.20200603082037-a48b9700bb81 h1:gGp4NCf/2N2epcNdVEqwF025gY0h6DOmS7xS7DciyZI= -github.com/secrethub/secrethub-go v0.27.1-0.20200603082037-a48b9700bb81/go.mod h1:Wr4gXWrk8OvBHiCttjLq7wFdKSm07rlEhq5OSYPemtI= -github.com/secrethub/secrethub-go v0.27.1-0.20200603102047-1a4e50eafb91/go.mod h1:Wr4gXWrk8OvBHiCttjLq7wFdKSm07rlEhq5OSYPemtI= -github.com/secrethub/secrethub-go v0.29.0 h1:BUM7lcxmjJENNF6pxq13dKPXf4sP6iQKWq7cbLbOM0g= -github.com/secrethub/secrethub-go v0.29.0/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= @@ -233,8 +225,6 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -338,8 +328,6 @@ google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/ google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.25.0 h1:LodzhlzZEUfhXzNUMIfVlf9Gr6Ua5MMtoFWh7+f47qA= -google.golang.org/api v0.25.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.26.0 h1:VJZ8h6E8ip82FRpQl848c5vAadxlTXrUh8RzQzSRm08= google.golang.org/api v0.26.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -369,8 +357,6 @@ google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84 h1:pSLkPbrjnPyLDYUO2VM9mDLqo2V6CFBY84lFSZAfoi4= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -388,15 +374,14 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc h1:TnonUr8u3himcMY0vSh23jFOXA+cnucl1gB6EQTReBI= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/internals/secrethub/service_gcp.go b/internals/secrethub/service_gcp.go index ab9ee0d8..16852594 100644 --- a/internals/secrethub/service_gcp.go +++ b/internals/secrethub/service_gcp.go @@ -24,4 +24,7 @@ func (cmd *ServiceGCPCommand) Register(r command.Registerer) { clause := r.Command("gcp", "Manage GCP service accounts.").Hidden() NewServiceGCPInitCommand(cmd.io, cmd.newClient).Register(clause) NewServiceGCPLsCommand(cmd.io, cmd.newClient).Register(clause) + NewServiceGCPLinkCommand(cmd.io, cmd.newClient).Register(clause) + NewServiceGCPListLinksCommand(cmd.io, cmd.newClient).Register(clause) + NewServiceGCPDeleteLinkCommand(cmd.io, cmd.newClient).Register(clause) } diff --git a/internals/secrethub/service_gcp_link.go b/internals/secrethub/service_gcp_link.go new file mode 100644 index 00000000..31f75da0 --- /dev/null +++ b/internals/secrethub/service_gcp_link.go @@ -0,0 +1,193 @@ +package secrethub + +import ( + "fmt" + "os/exec" + "runtime" + "time" + + "github.com/secrethub/secrethub-cli/internals/cli/progress" + "github.com/secrethub/secrethub-cli/internals/cli/ui" + "github.com/secrethub/secrethub-cli/internals/secrethub/command" + "github.com/secrethub/secrethub-go/internals/api" + "github.com/secrethub/secrethub-go/pkg/secrethub" +) + +// ServiceGCPLinkCommand create a new link between a SecretHub namespace and a GCP project. +type ServiceGCPLinkCommand struct { + namespace string + projectID string + io ui.IO + newClient newClientFunc +} + +// NewServiceGCPLinkCommand creates a new ServiceGCPLinkCommand. +func NewServiceGCPLinkCommand(io ui.IO, newClient newClientFunc) *ServiceGCPLinkCommand { + return &ServiceGCPLinkCommand{ + io: io, + newClient: newClient, + } +} + +func (cmd *ServiceGCPLinkCommand) Run() error { + client, err := cmd.newClient() + if err != nil { + return err + } + + _, err = client.IDPLinks().GCP().Get(cmd.namespace, cmd.projectID) + if !api.IsErrNotFound(err) { + fmt.Fprintf(cmd.io.Output(), "Namespace %s and GCP project %s are already linked.\n", cmd.namespace, cmd.projectID) + return nil + } + + return createGCPLink(client, cmd.io, cmd.namespace, cmd.projectID) +} + +func (cmd *ServiceGCPLinkCommand) Register(r command.Registerer) { + clause := r.Command("link", "Create a new link between a namespace and a GCP project to allow creating SecretHub service accounts for GCP Service Accounts in the GCP project.") + clause.Arg("namespace", "The SecretHub namespace to link.").Required().StringVar(&cmd.namespace) + clause.Arg("project-id", "The GCP project to link the namespace to.").Required().StringVar(&cmd.projectID) + + command.BindAction(clause, cmd.Run) +} + +// ServiceGCPListLinksCommand lists all existing links between the given namespace and GCP projects +type ServiceGCPListLinksCommand struct { + namespace string + useTimestamps bool + io ui.IO + newClient newClientFunc +} + +func NewServiceGCPListLinksCommand(io ui.IO, newClient newClientFunc) *ServiceGCPListLinksCommand { + return &ServiceGCPListLinksCommand{ + io: io, + newClient: newClient, + } +} + +func (cmd *ServiceGCPListLinksCommand) Run() error { + timeFormatter := NewTimeFormatter(cmd.useTimestamps) + + client, err := cmd.newClient() + if err != nil { + return err + } + + links, err := client.IDPLinks().GCP().List(cmd.namespace) + if err != nil { + return err + } + + f := newTableFormatter(cmd.io.Output(), 80, []tableColumn{ + {name: "Project ID"}, {name: "Created at", maxWidth: 22}, + }) + for _, link := range links { + err := f.Write([]string{link.LinkedID, timeFormatter.Format(link.CreatedAt)}) + if err != nil { + return err + } + } + + return nil +} + +func (cmd *ServiceGCPListLinksCommand) Register(r command.Registerer) { + clause := r.Command("list-links", "List all existing links between the given namespace and GCP projects.") + clause.Arg("namespace", "The namespace for which to list all existing links to GCP projects.").Required().StringVar(&cmd.namespace) + + registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) + + command.BindAction(clause, cmd.Run) +} + +// ServiceGCPDeleteLinkCommand deletes the link between a SecretHub namespace and a GCP project. +type ServiceGCPDeleteLinkCommand struct { + namespace string + projectID string + io ui.IO + newClient newClientFunc +} + +func NewServiceGCPDeleteLinkCommand(io ui.IO, newClient newClientFunc) *ServiceGCPDeleteLinkCommand { + return &ServiceGCPDeleteLinkCommand{ + io: io, + newClient: newClient, + } +} + +func (cmd *ServiceGCPDeleteLinkCommand) Register(r command.Registerer) { + clause := r.Command("delete-link", "Delete the link between a SecretHub namespace and a GCP project.") + clause.Arg("namespace", "The SecretHub namespace to delete the link from.").Required().StringVar(&cmd.namespace) + clause.Arg("project-id", "The GCP project to delete the link to.").Required().StringVar(&cmd.projectID) + + command.BindAction(clause, cmd.Run) +} + +func (cmd *ServiceGCPDeleteLinkCommand) Run() error { + client, err := cmd.newClient() + if err != nil { + return err + } + + _, err = client.IDPLinks().GCP().Get(cmd.namespace, cmd.projectID) + if api.IsErrNotFound(err) { + return err + } + + question := fmt.Sprintf("Are you sure you want to delete the link link between GCP project %s and the namespace %s? This does not affect any existing service accounts.", cmd.projectID, cmd.namespace) + confirm, err := ui.AskYesNo(cmd.io, question, ui.DefaultNo) + if err != nil { + return err + } else if !confirm { + fmt.Println("Aborting.") + return nil + } + + return client.IDPLinks().GCP().Delete(cmd.namespace, cmd.projectID) +} + +func createGCPLink(client secrethub.ClientInterface, io ui.IO, namespace, projectID string) error { + l, err := client.IDPLinks().GCP().AuthorizationCodeListener() + if err != nil { + return fmt.Errorf("could not set up listener for authorization process: %s", err) + } + + fmt.Fprintf(io.Output(), "If the browser does not automatically open, please go to the following link in your web browser: \n\n%s\n\n", l.AuthorizeURL()) + _ = openBrowser(l.AuthorizeURL()) + + fmt.Fprint(io.Output(), "Waiting for you to complete authorization process...") + progressPrinter := progress.NewPrinter(io.Output(), 2*time.Second) + progressPrinter.Start() + + authorizationCode, err := l.WaitForAuthorizationCode() + if err != nil { + progressPrinter.Stop() + return fmt.Errorf("could not retrieve authorization code: %s", err) + } + + progressPrinter.Stop() + + _, err = client.IDPLinks().GCP().Create(namespace, projectID, authorizationCode, l.ListenURL()) + if err != nil { + return err + } + + fmt.Fprintf(io.Output(), "Created link between GCP project %s and SecretHub namespace %s\n", projectID, namespace) + + return nil +} + +func openBrowser(url string) error { + switch runtime.GOOS { + case "linux": + return exec.Command("xdg-open", url).Start() + case "windows": + return exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start() + case "darwin": + return exec.Command("open", url).Start() + default: + return fmt.Errorf("unsupported platform") + } +} From 8cc73dbbb88e97ed5857ff7d37cd201346bc52ba Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Tue, 23 Jun 2020 15:02:03 +0200 Subject: [PATCH 02/37] Suggest to create IDP link during service init when it does not yet exist --- internals/secrethub/service_gcp_init.go | 26 +++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/internals/secrethub/service_gcp_init.go b/internals/secrethub/service_gcp_init.go index 8e41558a..880af375 100644 --- a/internals/secrethub/service_gcp_init.go +++ b/internals/secrethub/service_gcp_init.go @@ -2,6 +2,7 @@ package secrethub import ( "context" + "errors" "fmt" "strings" "sync" @@ -108,6 +109,31 @@ func (cmd *ServiceGCPInitCommand) Run() error { cmd.description = "GCP Service Account " + roleNameFromRole(cmd.serviceAccountEmail) } + projectID, err := api.ProjectIDFromGCPEmail(cmd.serviceAccountEmail) + if err != nil { + return fmt.Errorf("invalid service account email: %s", err) + } + + _, err = client.IDPLinks().GCP().Get(cmd.repo.GetNamespace(), projectID) + if api.IsErrNotFound(err) { + fmt.Fprintf(cmd.io.Output(), "GCP project %s is not yet linked to the namespace %s. ", projectID, cmd.repo.GetNamespace()) + + confirm, err := ui.AskYesNo(cmd.io, "Do you want to create this link now?", ui.DefaultYes) + if err != nil { + return err + } + if !confirm { + return errors.New("link between SecretHub organization and GCP project is required to continue") + } + + err = createGCPLink(client, cmd.io, cmd.repo.GetNamespace(), projectID) + if err != nil { + return fmt.Errorf("could not create link: %s", err) + } + } else if err != nil { + return err + } + service, err := client.Services().Create(cmd.repo.Value(), cmd.description, credentials.CreateGCPServiceAccount(cmd.serviceAccountEmail, cmd.kmsKeyResourceID)) if err == api.ErrCredentialAlreadyExists { return ErrRoleAlreadyTaken From 00340eab4d438e6b040d8ed61182e901937f53a1 Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Wed, 24 Jun 2020 15:10:11 +0200 Subject: [PATCH 03/37] Clarify consequence of deleting link Co-authored-by: Floris van der Grinten --- internals/secrethub/service_gcp_link.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internals/secrethub/service_gcp_link.go b/internals/secrethub/service_gcp_link.go index 31f75da0..0370bd33 100644 --- a/internals/secrethub/service_gcp_link.go +++ b/internals/secrethub/service_gcp_link.go @@ -136,7 +136,7 @@ func (cmd *ServiceGCPDeleteLinkCommand) Run() error { return err } - question := fmt.Sprintf("Are you sure you want to delete the link link between GCP project %s and the namespace %s? This does not affect any existing service accounts.", cmd.projectID, cmd.namespace) + question := fmt.Sprintf("Are you sure you want to delete the link link between GCP project %s and the namespace %s? Without the link, you cannot create new service accounts for this GCP project. This does not affect existing service accounts.", cmd.projectID, cmd.namespace) confirm, err := ui.AskYesNo(cmd.io, question, ui.DefaultNo) if err != nil { return err From 5404add8f82eee7176bcd38a463ad4d0c61cdebb Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Wed, 24 Jun 2020 14:56:44 +0200 Subject: [PATCH 04/37] Make listing behaviour equal to other ls commands --- internals/secrethub/service_gcp_link.go | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/internals/secrethub/service_gcp_link.go b/internals/secrethub/service_gcp_link.go index 0370bd33..aecdd148 100644 --- a/internals/secrethub/service_gcp_link.go +++ b/internals/secrethub/service_gcp_link.go @@ -4,6 +4,7 @@ import ( "fmt" "os/exec" "runtime" + "text/tabwriter" "time" "github.com/secrethub/secrethub-cli/internals/cli/progress" @@ -80,16 +81,21 @@ func (cmd *ServiceGCPListLinksCommand) Run() error { return err } - f := newTableFormatter(cmd.io.Output(), 80, []tableColumn{ - {name: "Project ID"}, {name: "Created at", maxWidth: 22}, - }) + tw := tabwriter.NewWriter(cmd.io.Output(), 0, 2, 2, ' ', 0) + fmt.Fprintf(tw, "%s\t%s\n", "PROJECT ID", "CREATED") + for _, link := range links { - err := f.Write([]string{link.LinkedID, timeFormatter.Format(link.CreatedAt)}) + _, err := fmt.Fprintf(tw, "%s\t%s\n", link.LinkedID, timeFormatter.Format(link.CreatedAt)) if err != nil { return err } } + err = tw.Flush() + if err != nil { + return err + } + return nil } From 7851cf082087a98bcde7e63f901f4c3cb31bbaf4 Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Thu, 25 Jun 2020 15:15:24 +0200 Subject: [PATCH 05/37] Fix already exists check --- internals/secrethub/service_gcp_link.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/internals/secrethub/service_gcp_link.go b/internals/secrethub/service_gcp_link.go index aecdd148..299b8dc2 100644 --- a/internals/secrethub/service_gcp_link.go +++ b/internals/secrethub/service_gcp_link.go @@ -37,7 +37,9 @@ func (cmd *ServiceGCPLinkCommand) Run() error { } _, err = client.IDPLinks().GCP().Get(cmd.namespace, cmd.projectID) - if !api.IsErrNotFound(err) { + if err != nil && !api.IsErrNotFound(err) { + return err + } else if err == nil { fmt.Fprintf(cmd.io.Output(), "Namespace %s and GCP project %s are already linked.\n", cmd.namespace, cmd.projectID) return nil } From 9117f2f88c86b5a7c537b340f0d477d5ddd919d2 Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Thu, 25 Jun 2020 16:01:45 +0200 Subject: [PATCH 06/37] Validate org names and project ID --- internals/secrethub/service_gcp_link.go | 44 ++++++++++++++++--------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/internals/secrethub/service_gcp_link.go b/internals/secrethub/service_gcp_link.go index 299b8dc2..509be63a 100644 --- a/internals/secrethub/service_gcp_link.go +++ b/internals/secrethub/service_gcp_link.go @@ -16,8 +16,8 @@ import ( // ServiceGCPLinkCommand create a new link between a SecretHub namespace and a GCP project. type ServiceGCPLinkCommand struct { - namespace string - projectID string + namespace api.OrgName + projectID gcpProjectID io ui.IO newClient newClientFunc } @@ -36,7 +36,7 @@ func (cmd *ServiceGCPLinkCommand) Run() error { return err } - _, err = client.IDPLinks().GCP().Get(cmd.namespace, cmd.projectID) + _, err = client.IDPLinks().GCP().Get(cmd.namespace.String(), cmd.projectID.String()) if err != nil && !api.IsErrNotFound(err) { return err } else if err == nil { @@ -44,20 +44,20 @@ func (cmd *ServiceGCPLinkCommand) Run() error { return nil } - return createGCPLink(client, cmd.io, cmd.namespace, cmd.projectID) + return createGCPLink(client, cmd.io, cmd.namespace.String(), cmd.projectID.String()) } func (cmd *ServiceGCPLinkCommand) Register(r command.Registerer) { clause := r.Command("link", "Create a new link between a namespace and a GCP project to allow creating SecretHub service accounts for GCP Service Accounts in the GCP project.") - clause.Arg("namespace", "The SecretHub namespace to link.").Required().StringVar(&cmd.namespace) - clause.Arg("project-id", "The GCP project to link the namespace to.").Required().StringVar(&cmd.projectID) + clause.Arg("namespace", "The SecretHub namespace to link.").Required().SetValue(&cmd.namespace) + clause.Arg("project-id", "The GCP project to link the namespace to.").Required().SetValue(&cmd.projectID) command.BindAction(clause, cmd.Run) } // ServiceGCPListLinksCommand lists all existing links between the given namespace and GCP projects type ServiceGCPListLinksCommand struct { - namespace string + namespace api.Namespace useTimestamps bool io ui.IO newClient newClientFunc @@ -78,7 +78,7 @@ func (cmd *ServiceGCPListLinksCommand) Run() error { return err } - links, err := client.IDPLinks().GCP().List(cmd.namespace) + links, err := client.IDPLinks().GCP().List(cmd.namespace.String()) if err != nil { return err } @@ -103,7 +103,7 @@ func (cmd *ServiceGCPListLinksCommand) Run() error { func (cmd *ServiceGCPListLinksCommand) Register(r command.Registerer) { clause := r.Command("list-links", "List all existing links between the given namespace and GCP projects.") - clause.Arg("namespace", "The namespace for which to list all existing links to GCP projects.").Required().StringVar(&cmd.namespace) + clause.Arg("namespace", "The namespace for which to list all existing links to GCP projects.").Required().SetValue(&cmd.namespace) registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) @@ -112,8 +112,8 @@ func (cmd *ServiceGCPListLinksCommand) Register(r command.Registerer) { // ServiceGCPDeleteLinkCommand deletes the link between a SecretHub namespace and a GCP project. type ServiceGCPDeleteLinkCommand struct { - namespace string - projectID string + namespace api.Namespace + projectID gcpProjectID io ui.IO newClient newClientFunc } @@ -127,8 +127,8 @@ func NewServiceGCPDeleteLinkCommand(io ui.IO, newClient newClientFunc) *ServiceG func (cmd *ServiceGCPDeleteLinkCommand) Register(r command.Registerer) { clause := r.Command("delete-link", "Delete the link between a SecretHub namespace and a GCP project.") - clause.Arg("namespace", "The SecretHub namespace to delete the link from.").Required().StringVar(&cmd.namespace) - clause.Arg("project-id", "The GCP project to delete the link to.").Required().StringVar(&cmd.projectID) + clause.Arg("namespace", "The SecretHub namespace to delete the link from.").Required().SetValue(&cmd.namespace) + clause.Arg("project-id", "The GCP project to delete the link to.").Required().SetValue(&cmd.projectID) command.BindAction(clause, cmd.Run) } @@ -139,7 +139,7 @@ func (cmd *ServiceGCPDeleteLinkCommand) Run() error { return err } - _, err = client.IDPLinks().GCP().Get(cmd.namespace, cmd.projectID) + _, err = client.IDPLinks().GCP().Get(cmd.namespace.String(), cmd.projectID.String()) if api.IsErrNotFound(err) { return err } @@ -153,7 +153,21 @@ func (cmd *ServiceGCPDeleteLinkCommand) Run() error { return nil } - return client.IDPLinks().GCP().Delete(cmd.namespace, cmd.projectID) + return client.IDPLinks().GCP().Delete(cmd.namespace.String(), cmd.projectID.String()) +} + +type gcpProjectID string + +func (g *gcpProjectID) String() string { + return string(*g) +} + +func (g *gcpProjectID) Set(s string) error { + if err := api.ValidateGCPProjectID(s); err != nil { + return err + } + *g = gcpProjectID(s) + return nil } func createGCPLink(client secrethub.ClientInterface, io ui.IO, namespace, projectID string) error { From 4f04395fb9bd98e423075b8d221f23d6acbf22ef Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Fri, 26 Jun 2020 10:50:12 +0200 Subject: [PATCH 07/37] Replace Get() with Exists() where applicable --- go.mod | 2 +- go.sum | 5 +++++ internals/secrethub/service_gcp_link.go | 14 +++++++++----- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 2a4828a5..06508a3c 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/pkg/errors v0.9.1 // indirect github.com/secrethub/demo-app v0.1.0 - github.com/secrethub/secrethub-go v0.29.1-0.20200623115223-14e18aeb8f96 + github.com/secrethub/secrethub-go v0.29.1-0.20200626075900-f7c68f70dc36 github.com/zalando/go-keyring v0.0.0-20190208082241-fbe81aec3a07 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d diff --git a/go.sum b/go.sum index b99f9ca5..e11c9a08 100644 --- a/go.sum +++ b/go.sum @@ -157,9 +157,13 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/secrethub/demo-app v0.1.0 h1:HwPPxuiSvx4TBE7Qppzu3A9eHqmsBrIz4Ko8u8pqMqw= github.com/secrethub/demo-app v0.1.0/go.mod h1:ymjm8+WXTSDTFqsGVBNVmHSnwtZMYi7KptHvpo/fLH4= github.com/secrethub/secrethub-cli v0.30.0/go.mod h1:dC0wd40v+iQdV83/0rUrOa01LYq+8Yj2AtJB1vzh2ao= +github.com/secrethub/secrethub-go v0.21.0/go.mod h1:rc2IfKKBJ4L0wGec0u4XnF5/pe0FFPE4Q1MWfrFso7s= +github.com/secrethub/secrethub-go v0.29.1-0.20200626075900-f7c68f70dc36 h1:kRVdL7PRfR80xjpOxFy1O0JROVpILWc2FZWE7Ni2Z2M= +github.com/secrethub/secrethub-go v0.29.1-0.20200626075900-f7c68f70dc36/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= @@ -225,6 +229,7 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= diff --git a/internals/secrethub/service_gcp_link.go b/internals/secrethub/service_gcp_link.go index 509be63a..28b57071 100644 --- a/internals/secrethub/service_gcp_link.go +++ b/internals/secrethub/service_gcp_link.go @@ -36,10 +36,11 @@ func (cmd *ServiceGCPLinkCommand) Run() error { return err } - _, err = client.IDPLinks().GCP().Get(cmd.namespace.String(), cmd.projectID.String()) - if err != nil && !api.IsErrNotFound(err) { + exists, err := client.IDPLinks().GCP().Exists(cmd.namespace.String(), cmd.projectID.String()) + if err != nil { return err - } else if err == nil { + } + if exists { fmt.Fprintf(cmd.io.Output(), "Namespace %s and GCP project %s are already linked.\n", cmd.namespace, cmd.projectID) return nil } @@ -139,10 +140,13 @@ func (cmd *ServiceGCPDeleteLinkCommand) Run() error { return err } - _, err = client.IDPLinks().GCP().Get(cmd.namespace.String(), cmd.projectID.String()) - if api.IsErrNotFound(err) { + exists, err := client.IDPLinks().GCP().Exists(cmd.namespace.String(), cmd.projectID.String()) + if err != nil { return err } + if !exists { + return fmt.Errorf("no existing link between GCP project %s and namespace %s found", cmd.projectID, cmd.namespace) + } question := fmt.Sprintf("Are you sure you want to delete the link link between GCP project %s and the namespace %s? Without the link, you cannot create new service accounts for this GCP project. This does not affect existing service accounts.", cmd.projectID, cmd.namespace) confirm, err := ui.AskYesNo(cmd.io, question, ui.DefaultNo) From ac30d0561bca19546378afbd2ee197c1bae5d131 Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Fri, 26 Jun 2020 10:50:44 +0200 Subject: [PATCH 08/37] Add long help text to link command --- internals/secrethub/service_gcp_link.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/internals/secrethub/service_gcp_link.go b/internals/secrethub/service_gcp_link.go index 28b57071..301c6a76 100644 --- a/internals/secrethub/service_gcp_link.go +++ b/internals/secrethub/service_gcp_link.go @@ -53,6 +53,21 @@ func (cmd *ServiceGCPLinkCommand) Register(r command.Registerer) { clause.Arg("namespace", "The SecretHub namespace to link.").Required().SetValue(&cmd.namespace) clause.Arg("project-id", "The GCP project to link the namespace to.").Required().SetValue(&cmd.projectID) + clause.HelpLong("Linking a GCP project to a namespace is required to create SecretHub service accounts that use a GCP Service Account within the project. " + + "A SecretHub namespace can be linked to multiple GCP projects and a GCP project can be linked to multiple namespaces.\n" + + "\n" + + "As long as the link exists, new service accounts can be created for the GCP project. " + + "If a link is deleted, no new services can be created, but previously created services are unaffected. \n" + + "\n" + + "This command will open browser where you are asked to authorize SecretHub to perform iam.test on your GCP projects. " + + "This authorization is used to verify that you have access to the specified GCP project. " + + "It is therefore important that the GCP account selected during the authorization process has access to the GCP project.\n" + + "\n" + + "Once the granted authorization has been used to confirm your access to the GCP project, the authorization will automatically be revoked. " + + "This can be verified by going to https://myaccount.google.com/permissions. " + + "Any reference to SecretHub should automatically disappear within a few minutes. " + + "If it does not, the access can safely be revoked manually.") + command.BindAction(clause, cmd.Run) } From 3149b603bd3fa20037b64d2c87b0ce491779f17c Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Fri, 26 Jun 2020 13:02:28 +0200 Subject: [PATCH 09/37] Better explain to the user what the process of linking looks like --- internals/secrethub/service_gcp_init.go | 2 +- internals/secrethub/service_gcp_link.go | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/internals/secrethub/service_gcp_init.go b/internals/secrethub/service_gcp_init.go index 880af375..8de72896 100644 --- a/internals/secrethub/service_gcp_init.go +++ b/internals/secrethub/service_gcp_init.go @@ -116,7 +116,7 @@ func (cmd *ServiceGCPInitCommand) Run() error { _, err = client.IDPLinks().GCP().Get(cmd.repo.GetNamespace(), projectID) if api.IsErrNotFound(err) { - fmt.Fprintf(cmd.io.Output(), "GCP project %s is not yet linked to the namespace %s. ", projectID, cmd.repo.GetNamespace()) + fmt.Fprintf(cmd.io.Output(), "GCP project %s is not yet linked to the namespace %s. This link is needed to create SecretHub service accounts for GCP Service Accounts in the GCP project %s. This link only has to be created once for each SecretHub namespace.\n\n", projectID, cmd.repo.GetNamespace(), projectID) confirm, err := ui.AskYesNo(cmd.io, "Do you want to create this link now?", ui.DefaultYes) if err != nil { diff --git a/internals/secrethub/service_gcp_link.go b/internals/secrethub/service_gcp_link.go index 301c6a76..e134510d 100644 --- a/internals/secrethub/service_gcp_link.go +++ b/internals/secrethub/service_gcp_link.go @@ -195,7 +195,17 @@ func createGCPLink(client secrethub.ClientInterface, io ui.IO, namespace, projec return fmt.Errorf("could not set up listener for authorization process: %s", err) } - fmt.Fprintf(io.Output(), "If the browser does not automatically open, please go to the following link in your web browser: \n\n%s\n\n", l.AuthorizeURL()) + fmt.Fprintf(io.Output(), "To create a link between the GCP project %s and the SecretHub namespace %s we have to verify your access to this GCP project. "+ + "After pressing [ENTER], a browser window will open and ask you to login to a Google account. "+ + "Please select an account that has read access to the GCP project. "+ + "You will then be asked to grant `Test IAM Permissions` permission to SecretHub. "+ + "This will be used to check whether you do have access to the project. "+ + "After this check has succeeed, the access will directly be revoked.\n\n", projectID, namespace) + + // If this fails, just continue. + _, _ = ui.Ask(io, "Press [ENTER] to continue") + + fmt.Fprintf(io.Output(), "If the browser did not automatically open, please manually go to the following address in your browser: \n\n%s\n\n", l.AuthorizeURL()) _ = openBrowser(l.AuthorizeURL()) fmt.Fprint(io.Output(), "Waiting for you to complete authorization process...") From b5e27bf90ac5ef6c96063f0450a1e9d824020643 Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Wed, 1 Jul 2020 14:11:25 +0200 Subject: [PATCH 10/37] Fix typo Co-authored-by: Simon Barendse --- internals/secrethub/service_gcp_link.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internals/secrethub/service_gcp_link.go b/internals/secrethub/service_gcp_link.go index e134510d..573237ef 100644 --- a/internals/secrethub/service_gcp_link.go +++ b/internals/secrethub/service_gcp_link.go @@ -59,7 +59,7 @@ func (cmd *ServiceGCPLinkCommand) Register(r command.Registerer) { "As long as the link exists, new service accounts can be created for the GCP project. " + "If a link is deleted, no new services can be created, but previously created services are unaffected. \n" + "\n" + - "This command will open browser where you are asked to authorize SecretHub to perform iam.test on your GCP projects. " + + "This command will open your browser where you are asked to authorize SecretHub to perform iam.test on your GCP projects. " + "This authorization is used to verify that you have access to the specified GCP project. " + "It is therefore important that the GCP account selected during the authorization process has access to the GCP project.\n" + "\n" + From a7f120fd179142b1131ee2416627b0475d178722 Mon Sep 17 00:00:00 2001 From: Simon Barendse Date: Wed, 1 Jul 2020 17:57:32 +0200 Subject: [PATCH 11/37] Move all app construction to secrethub.NewApp function --- internals/secrethub/app.go | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/internals/secrethub/app.go b/internals/secrethub/app.go index 346cc69c..803f1af5 100644 --- a/internals/secrethub/app.go +++ b/internals/secrethub/app.go @@ -86,7 +86,8 @@ func NewApp() *App { "The CLI is configurable through command-line flags and environment variables. " + "Options set on the command-line take precedence over those set in the environment. " + "The format for environment variables is `SECRETHUB_[COMMAND_]FLAG_NAME`." - return &App{ + + app := App{ cli: cli.NewApp(ApplicationName, help).ExtraEnvVarFunc( func(key string) bool { return strings.HasPrefix(key, "SECRETHUB_VAR_") @@ -97,18 +98,7 @@ func NewApp() *App { io: io, logger: cli.NewLogger(), } -} -// Version adds a flag for displaying the application version number. -func (app *App) Version(version string, commit string) *App { - app.cli = app.cli.Version(ApplicationName + " version " + version + ", build " + commit) - return app -} - -// Run builds the command-line application, parses the arguments, -// configures global behavior and executes the command given by the args. -func (app *App) Run(args []string) error { - // Construct the CLI RegisterDebugFlag(app.cli, app.logger) RegisterMlockFlag(app.cli) RegisterColorFlag(app.cli) @@ -147,6 +137,18 @@ func (app *App) Run(args []string) error { }, }) + return &app +} + +// Version adds a flag for displaying the application version number. +func (app *App) Version(version string, commit string) *App { + app.cli = app.cli.Version(ApplicationName + " version " + version + ", build " + commit) + return app +} + +// Run builds the command-line application, parses the arguments, +// configures global behavior and executes the command given by the args. +func (app *App) Run(args []string) error { // Parse also executes the command when parsing is successful. _, err := app.cli.Parse(args) return err From 5fe45f3099cb3ef35d92f84862b36ef66377b362 Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Tue, 30 Jun 2020 14:19:50 +0200 Subject: [PATCH 12/37] Remove Exists() function and no longer prompt when not existing It's not like the user has a choice anyway. --- internals/secrethub/service_gcp_init.go | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/internals/secrethub/service_gcp_init.go b/internals/secrethub/service_gcp_init.go index 8de72896..dffc752d 100644 --- a/internals/secrethub/service_gcp_init.go +++ b/internals/secrethub/service_gcp_init.go @@ -2,7 +2,6 @@ package secrethub import ( "context" - "errors" "fmt" "strings" "sync" @@ -14,9 +13,10 @@ import ( "google.golang.org/api/option" "google.golang.org/api/transport" + "github.com/secrethub/secrethub-go/internals/gcp" + "github.com/secrethub/secrethub-cli/internals/cli/ui" "github.com/secrethub/secrethub-cli/internals/secrethub/command" - "github.com/secrethub/secrethub-go/internals/gcp" "github.com/secrethub/secrethub-go/internals/api" "github.com/secrethub/secrethub-go/pkg/secrethub/credentials" @@ -114,24 +114,17 @@ func (cmd *ServiceGCPInitCommand) Run() error { return fmt.Errorf("invalid service account email: %s", err) } - _, err = client.IDPLinks().GCP().Get(cmd.repo.GetNamespace(), projectID) - if api.IsErrNotFound(err) { - fmt.Fprintf(cmd.io.Output(), "GCP project %s is not yet linked to the namespace %s. This link is needed to create SecretHub service accounts for GCP Service Accounts in the GCP project %s. This link only has to be created once for each SecretHub namespace.\n\n", projectID, cmd.repo.GetNamespace(), projectID) - - confirm, err := ui.AskYesNo(cmd.io, "Do you want to create this link now?", ui.DefaultYes) - if err != nil { - return err - } - if !confirm { - return errors.New("link between SecretHub organization and GCP project is required to continue") - } + exists, err := client.IDPLinks().GCP().Exists(cmd.repo.GetNamespace(), projectID) + if err != nil { + return err + } + if !exists { + fmt.Fprintf(cmd.io.Output(), "This is the first time you're using a GCP Service Account in the GCP project %s for a SecretHub service account in the namespace %s. You have to link these two first.\n\n", projectID, cmd.repo.GetNamespace()) err = createGCPLink(client, cmd.io, cmd.repo.GetNamespace(), projectID) if err != nil { return fmt.Errorf("could not create link: %s", err) } - } else if err != nil { - return err } service, err := client.Services().Create(cmd.repo.Value(), cmd.description, credentials.CreateGCPServiceAccount(cmd.serviceAccountEmail, cmd.kmsKeyResourceID)) From 509b4519fe99227abffd12d5e7f0a36c9fbe7768 Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Tue, 30 Jun 2020 14:22:22 +0200 Subject: [PATCH 13/37] Use new WithAuthorizationCode instead of WaitFor.. This makes sure the user is redirected to a user-friendly page instead of getting just a text response. --- go.mod | 2 +- go.sum | 2 ++ internals/secrethub/service_gcp_link.go | 14 ++++++-------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 06508a3c..9402bbe5 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/pkg/errors v0.9.1 // indirect github.com/secrethub/demo-app v0.1.0 - github.com/secrethub/secrethub-go v0.29.1-0.20200626075900-f7c68f70dc36 + github.com/secrethub/secrethub-go v0.29.1-0.20200630121846-9adfc0eb3add github.com/zalando/go-keyring v0.0.0-20190208082241-fbe81aec3a07 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d diff --git a/go.sum b/go.sum index e11c9a08..e65e38c3 100644 --- a/go.sum +++ b/go.sum @@ -164,6 +164,8 @@ github.com/secrethub/secrethub-cli v0.30.0/go.mod h1:dC0wd40v+iQdV83/0rUrOa01LYq github.com/secrethub/secrethub-go v0.21.0/go.mod h1:rc2IfKKBJ4L0wGec0u4XnF5/pe0FFPE4Q1MWfrFso7s= github.com/secrethub/secrethub-go v0.29.1-0.20200626075900-f7c68f70dc36 h1:kRVdL7PRfR80xjpOxFy1O0JROVpILWc2FZWE7Ni2Z2M= github.com/secrethub/secrethub-go v0.29.1-0.20200626075900-f7c68f70dc36/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= +github.com/secrethub/secrethub-go v0.29.1-0.20200630121846-9adfc0eb3add h1:+DzHsSjht15ycb7GFmyfmQ39gy8ZtA7FjWfJbWUPIYk= +github.com/secrethub/secrethub-go v0.29.1-0.20200630121846-9adfc0eb3add/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= diff --git a/internals/secrethub/service_gcp_link.go b/internals/secrethub/service_gcp_link.go index 573237ef..18a767c1 100644 --- a/internals/secrethub/service_gcp_link.go +++ b/internals/secrethub/service_gcp_link.go @@ -190,7 +190,7 @@ func (g *gcpProjectID) Set(s string) error { } func createGCPLink(client secrethub.ClientInterface, io ui.IO, namespace, projectID string) error { - l, err := client.IDPLinks().GCP().AuthorizationCodeListener() + l, err := client.IDPLinks().GCP().AuthorizationCodeListener(namespace, projectID) if err != nil { return fmt.Errorf("could not set up listener for authorization process: %s", err) } @@ -212,19 +212,17 @@ func createGCPLink(client secrethub.ClientInterface, io ui.IO, namespace, projec progressPrinter := progress.NewPrinter(io.Output(), 2*time.Second) progressPrinter.Start() - authorizationCode, err := l.WaitForAuthorizationCode() + err = l.WithAuthorizationCode(func(authorizationCode string, err error) error { + _, err = client.IDPLinks().GCP().Create(namespace, projectID, authorizationCode, l.ListenURL()) + return err + }) if err != nil { progressPrinter.Stop() - return fmt.Errorf("could not retrieve authorization code: %s", err) + return err } progressPrinter.Stop() - _, err = client.IDPLinks().GCP().Create(namespace, projectID, authorizationCode, l.ListenURL()) - if err != nil { - return err - } - fmt.Fprintf(io.Output(), "Created link between GCP project %s and SecretHub namespace %s\n", projectID, namespace) return nil From bf62a1ab042404dca8e1261a8f1a82eebbf080c6 Mon Sep 17 00:00:00 2001 From: Simon Barendse Date: Thu, 2 Jul 2020 12:14:45 +0200 Subject: [PATCH 14/37] Use identity provider link iterator --- go.mod | 2 +- go.sum | 2 ++ internals/secrethub/service_gcp_link.go | 19 +++++++++++-------- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 9402bbe5..f47f7ca2 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/pkg/errors v0.9.1 // indirect github.com/secrethub/demo-app v0.1.0 - github.com/secrethub/secrethub-go v0.29.1-0.20200630121846-9adfc0eb3add + github.com/secrethub/secrethub-go v0.29.1-0.20200702094400-d465926a4a6a github.com/zalando/go-keyring v0.0.0-20190208082241-fbe81aec3a07 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d diff --git a/go.sum b/go.sum index e65e38c3..b8150703 100644 --- a/go.sum +++ b/go.sum @@ -166,6 +166,8 @@ github.com/secrethub/secrethub-go v0.29.1-0.20200626075900-f7c68f70dc36 h1:kRVdL github.com/secrethub/secrethub-go v0.29.1-0.20200626075900-f7c68f70dc36/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= github.com/secrethub/secrethub-go v0.29.1-0.20200630121846-9adfc0eb3add h1:+DzHsSjht15ycb7GFmyfmQ39gy8ZtA7FjWfJbWUPIYk= github.com/secrethub/secrethub-go v0.29.1-0.20200630121846-9adfc0eb3add/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= +github.com/secrethub/secrethub-go v0.29.1-0.20200702094400-d465926a4a6a h1:rtFQLsSWGkdqd6LQFbgHsG/be60Cpqv8tc1w4XoKgKM= +github.com/secrethub/secrethub-go v0.29.1-0.20200702094400-d465926a4a6a/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= diff --git a/internals/secrethub/service_gcp_link.go b/internals/secrethub/service_gcp_link.go index 18a767c1..e4bed097 100644 --- a/internals/secrethub/service_gcp_link.go +++ b/internals/secrethub/service_gcp_link.go @@ -2,6 +2,7 @@ package secrethub import ( "fmt" + "github.com/secrethub/secrethub-go/pkg/secrethub/iterator" "os/exec" "runtime" "text/tabwriter" @@ -94,21 +95,23 @@ func (cmd *ServiceGCPListLinksCommand) Run() error { return err } - links, err := client.IDPLinks().GCP().List(cmd.namespace.String()) - if err != nil { - return err - } - tw := tabwriter.NewWriter(cmd.io.Output(), 0, 2, 2, ' ', 0) fmt.Fprintf(tw, "%s\t%s\n", "PROJECT ID", "CREATED") - for _, link := range links { - _, err := fmt.Fprintf(tw, "%s\t%s\n", link.LinkedID, timeFormatter.Format(link.CreatedAt)) + iter := client.IDPLinks().GCP().List(cmd.namespace.String(), &secrethub.IdpLinkIteratorParams{}) + for { + link, err := iter.Next() + if err == iterator.Done { + break + } else if err != nil { + return err + } + + _, err = fmt.Fprintf(tw, "%s\t%s\n", link.LinkedID, timeFormatter.Format(link.CreatedAt)) if err != nil { return err } } - err = tw.Flush() if err != nil { return err From 53b481fb456838cd0f75929daefc3ba2a15835ab Mon Sep 17 00:00:00 2001 From: Simon Barendse Date: Thu, 2 Jul 2020 13:26:21 +0200 Subject: [PATCH 15/37] Run linter in Docker This makes it possible to have different linter versions locally and makes sure "make lint" always runs with the version specified in the Makefile. --- Makefile | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index abe4f1b9..0085813e 100644 --- a/Makefile +++ b/Makefile @@ -3,8 +3,9 @@ commit: format lint test format: @goimports -w $(find . -type f -name '*.go') +GOLANGCI_VERSION=v1.23.8 lint: - @golangci-lint run + @docker run --rm -t -v $$(go env GOCACHE):/cache/go -e GOCACHE=/cache/go -e GOLANGCI_LINT_CACHE=/cache/go -v $$(go env GOPATH)/pkg:/go/pkg -v ${PWD}:/app -w /app golangci/golangci-lint:${GOLANGCI_VERSION}-alpine golangci-lint run ./... test: @go test -race ./... @@ -14,11 +15,6 @@ tools: format-tools lint-tools format-tools: @go get -u golang.org/x/tools/cmd/goimports -GOLANGCI_VERSION=v1.23.8 - -lint-tools: - @curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin ${GOLANGCI_VERSION} - COMMIT=`git rev-parse --short HEAD` VERSION=`git describe --always` BUILD_FLAGS=-ldflags "-s -w -X "github.com/secrethub/secrethub-cli/internals/secrethub.Commit=${COMMIT}" -X "github.com/secrethub/secrethub-cli/internals/secrethub.Version=${VERSION}"" -tags=production From 4b9a29ea42d8f59b8a0f94459ee8dea94d5b96b0 Mon Sep 17 00:00:00 2001 From: Simon Barendse Date: Thu, 2 Jul 2020 13:30:57 +0200 Subject: [PATCH 16/37] Fix typo "succeeed" => "succeeded" --- internals/secrethub/service_gcp_link.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internals/secrethub/service_gcp_link.go b/internals/secrethub/service_gcp_link.go index e4bed097..3b8d9ab8 100644 --- a/internals/secrethub/service_gcp_link.go +++ b/internals/secrethub/service_gcp_link.go @@ -203,7 +203,7 @@ func createGCPLink(client secrethub.ClientInterface, io ui.IO, namespace, projec "Please select an account that has read access to the GCP project. "+ "You will then be asked to grant `Test IAM Permissions` permission to SecretHub. "+ "This will be used to check whether you do have access to the project. "+ - "After this check has succeeed, the access will directly be revoked.\n\n", projectID, namespace) + "After this check has succeeded, the access will directly be revoked.\n\n", projectID, namespace) // If this fails, just continue. _, _ = ui.Ask(io, "Press [ENTER] to continue") From 87e5d8166c3fc46b25e6ca34214ea751b66be7e6 Mon Sep 17 00:00:00 2001 From: Simon Barendse Date: Thu, 2 Jul 2020 13:33:35 +0200 Subject: [PATCH 17/37] Order imports --- internals/secrethub/service_gcp_link.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internals/secrethub/service_gcp_link.go b/internals/secrethub/service_gcp_link.go index 3b8d9ab8..b2c1f2e4 100644 --- a/internals/secrethub/service_gcp_link.go +++ b/internals/secrethub/service_gcp_link.go @@ -2,7 +2,6 @@ package secrethub import ( "fmt" - "github.com/secrethub/secrethub-go/pkg/secrethub/iterator" "os/exec" "runtime" "text/tabwriter" @@ -13,6 +12,7 @@ import ( "github.com/secrethub/secrethub-cli/internals/secrethub/command" "github.com/secrethub/secrethub-go/internals/api" "github.com/secrethub/secrethub-go/pkg/secrethub" + "github.com/secrethub/secrethub-go/pkg/secrethub/iterator" ) // ServiceGCPLinkCommand create a new link between a SecretHub namespace and a GCP project. From 62371d2e52b2d3b6815f35ad68e39c8918e3c6fa Mon Sep 17 00:00:00 2001 From: Floris van der Grinten Date: Thu, 2 Jul 2020 13:35:48 +0200 Subject: [PATCH 18/37] Expose CLI app model --- internals/secrethub/app.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/internals/secrethub/app.go b/internals/secrethub/app.go index 803f1af5..e95a9c8b 100644 --- a/internals/secrethub/app.go +++ b/internals/secrethub/app.go @@ -154,6 +154,11 @@ func (app *App) Run(args []string) error { return err } +// Model returns the CLI application model containing all the SecretHub CLI commands, flags, and args. +func (app *App) Model() *kingpin.ApplicationModel { + return app.cli.Model() +} + // registerCommands initializes all commands and registers them on the app. func (app *App) registerCommands() { From 531f424b55892d3118531fccf1bda5875e8c21dc Mon Sep 17 00:00:00 2001 From: Simon Barendse Date: Thu, 2 Jul 2020 13:51:11 +0200 Subject: [PATCH 19/37] Remove unused error argument from authorization callback --- go.mod | 2 +- go.sum | 2 ++ internals/secrethub/service_gcp_link.go | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index f47f7ca2..c9cda312 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/pkg/errors v0.9.1 // indirect github.com/secrethub/demo-app v0.1.0 - github.com/secrethub/secrethub-go v0.29.1-0.20200702094400-d465926a4a6a + github.com/secrethub/secrethub-go v0.29.1-0.20200702114848-1a3657310d91 github.com/zalando/go-keyring v0.0.0-20190208082241-fbe81aec3a07 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d diff --git a/go.sum b/go.sum index b8150703..fe433d12 100644 --- a/go.sum +++ b/go.sum @@ -168,6 +168,8 @@ github.com/secrethub/secrethub-go v0.29.1-0.20200630121846-9adfc0eb3add h1:+DzHs github.com/secrethub/secrethub-go v0.29.1-0.20200630121846-9adfc0eb3add/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= github.com/secrethub/secrethub-go v0.29.1-0.20200702094400-d465926a4a6a h1:rtFQLsSWGkdqd6LQFbgHsG/be60Cpqv8tc1w4XoKgKM= github.com/secrethub/secrethub-go v0.29.1-0.20200702094400-d465926a4a6a/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= +github.com/secrethub/secrethub-go v0.29.1-0.20200702114848-1a3657310d91 h1:10KZJ3o7hodrTO1xAP1uNhDWSlLV9Bh9RqRFtiNCYJ4= +github.com/secrethub/secrethub-go v0.29.1-0.20200702114848-1a3657310d91/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= diff --git a/internals/secrethub/service_gcp_link.go b/internals/secrethub/service_gcp_link.go index b2c1f2e4..777f68cc 100644 --- a/internals/secrethub/service_gcp_link.go +++ b/internals/secrethub/service_gcp_link.go @@ -215,7 +215,7 @@ func createGCPLink(client secrethub.ClientInterface, io ui.IO, namespace, projec progressPrinter := progress.NewPrinter(io.Output(), 2*time.Second) progressPrinter.Start() - err = l.WithAuthorizationCode(func(authorizationCode string, err error) error { + err = l.WithAuthorizationCode(func(authorizationCode string) error { _, err = client.IDPLinks().GCP().Create(namespace, projectID, authorizationCode, l.ListenURL()) return err }) From c21ba1329ba6eae0a1449cbb9d3ce611e9d77a33 Mon Sep 17 00:00:00 2001 From: Simon Barendse Date: Thu, 2 Jul 2020 15:13:03 +0200 Subject: [PATCH 20/37] Run linter with the current user By running the linter as the current user instead of the root user, the files created (in the cache and module storage) are also owned by the user, so that they can still be used when running go as the current user. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0085813e..fa01f74e 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ format: GOLANGCI_VERSION=v1.23.8 lint: - @docker run --rm -t -v $$(go env GOCACHE):/cache/go -e GOCACHE=/cache/go -e GOLANGCI_LINT_CACHE=/cache/go -v $$(go env GOPATH)/pkg:/go/pkg -v ${PWD}:/app -w /app golangci/golangci-lint:${GOLANGCI_VERSION}-alpine golangci-lint run ./... + @docker run --rm -t --user $$(id -u):$$(id -g) -v $$(go env GOCACHE):/cache/go -e GOCACHE=/cache/go -e GOLANGCI_LINT_CACHE=/cache/go -v $$(go env GOPATH)/pkg:/go/pkg -v ${PWD}:/app -w /app golangci/golangci-lint:${GOLANGCI_VERSION}-alpine golangci-lint run ./... test: @go test -race ./... From 8dfa8e6ea8367b31e74240bfec6604d9197ec71d Mon Sep 17 00:00:00 2001 From: Simon Barendse Date: Fri, 3 Jul 2020 11:24:47 +0200 Subject: [PATCH 21/37] Update secrethub-go to latest develop --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index c9cda312..eb14554e 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/pkg/errors v0.9.1 // indirect github.com/secrethub/demo-app v0.1.0 - github.com/secrethub/secrethub-go v0.29.1-0.20200702114848-1a3657310d91 + github.com/secrethub/secrethub-go v0.29.1-0.20200703092019-9f5d3de9b0e4 github.com/zalando/go-keyring v0.0.0-20190208082241-fbe81aec3a07 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d diff --git a/go.sum b/go.sum index fe433d12..51061109 100644 --- a/go.sum +++ b/go.sum @@ -170,6 +170,8 @@ github.com/secrethub/secrethub-go v0.29.1-0.20200702094400-d465926a4a6a h1:rtFQL github.com/secrethub/secrethub-go v0.29.1-0.20200702094400-d465926a4a6a/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= github.com/secrethub/secrethub-go v0.29.1-0.20200702114848-1a3657310d91 h1:10KZJ3o7hodrTO1xAP1uNhDWSlLV9Bh9RqRFtiNCYJ4= github.com/secrethub/secrethub-go v0.29.1-0.20200702114848-1a3657310d91/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= +github.com/secrethub/secrethub-go v0.29.1-0.20200703092019-9f5d3de9b0e4 h1:TszZ+u/DRpPjaAGwEFSQNHkWhG4QR3KBxQJ66NfTAMk= +github.com/secrethub/secrethub-go v0.29.1-0.20200703092019-9f5d3de9b0e4/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= From 53d5a2ee5fdc8ceebb6f7edabfb4f83211a8b072 Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Fri, 3 Jul 2020 11:35:46 +0200 Subject: [PATCH 22/37] Unhide GCP IdP functionality This functionality is moving to GA. So no need to hide it any longer. --- internals/secrethub/client_factory.go | 4 ++-- internals/secrethub/service_gcp.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/internals/secrethub/client_factory.go b/internals/secrethub/client_factory.go index 64ce19ff..bd50bad2 100644 --- a/internals/secrethub/client_factory.go +++ b/internals/secrethub/client_factory.go @@ -12,7 +12,7 @@ import ( // Errors var ( - ErrUnknownIdentityProvider = errMain.Code("unknown_identity_provider").ErrorPref("%s is not a supported identity provider. Valid options are `aws` and `key`.") + ErrUnknownIdentityProvider = errMain.Code("unknown_identity_provider").ErrorPref("%s is not a supported identity provider. Valid options are `aws`, `gcp` and `key`.") ) // ClientFactory handles creating a new client with the configured options. @@ -42,7 +42,7 @@ type clientFactory struct { // Register the flags for configuration on a cli application. func (f *clientFactory) Register(r FlagRegisterer) { r.Flag("api-remote", "The SecretHub API address, don't set this unless you know what you're doing.").Hidden().URLVar(&f.ServerURL) - r.Flag("identity-provider", "Enable native authentication with a trusted identity provider. Options are `aws` (IAM + KMS) and `key`. When you run the CLI on one of the platforms, you can leverage their respective identity providers to do native keyless authentication. Defaults to key, which uses the default credential sourced from a file, command-line flag, or environment variable. ").Default("key").StringVar(&f.identityProvider) + r.Flag("identity-provider", "Enable native authentication with a trusted identity provider. Options are `aws` (IAM + KMS), `gcp` (IAM + KMS) and `key`. When you run the CLI on one of the platforms, you can leverage their respective identity providers to do native keyless authentication. Defaults to key, which uses the default credential sourced from a file, command-line flag, or environment variable. ").Default("key").StringVar(&f.identityProvider) r.Flag("proxy-address", "Set to the address of a proxy to connect to the API through a proxy. The prepended scheme determines the proxy type (http, https and socks5 are supported). For example: `--proxy-address http://my-proxy:1234`").URLVar(&f.proxyAddress) } diff --git a/internals/secrethub/service_gcp.go b/internals/secrethub/service_gcp.go index 16852594..67a7294b 100644 --- a/internals/secrethub/service_gcp.go +++ b/internals/secrethub/service_gcp.go @@ -21,7 +21,7 @@ func NewServiceGCPCommand(io ui.IO, newClient newClientFunc) *ServiceGCPCommand // Register registers the command and its sub-commands on the provided Registerer. func (cmd *ServiceGCPCommand) Register(r command.Registerer) { - clause := r.Command("gcp", "Manage GCP service accounts.").Hidden() + clause := r.Command("gcp", "Manage GCP service accounts.") NewServiceGCPInitCommand(cmd.io, cmd.newClient).Register(clause) NewServiceGCPLsCommand(cmd.io, cmd.newClient).Register(clause) NewServiceGCPLinkCommand(cmd.io, cmd.newClient).Register(clause) From 029df88a8f77f746956ed82c8561c8a5d4205df3 Mon Sep 17 00:00:00 2001 From: Simon Barendse Date: Fri, 3 Jul 2020 15:21:01 +0200 Subject: [PATCH 23/37] Explain impact of `service gcp delete-link` in long help text --- internals/secrethub/service_gcp_link.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internals/secrethub/service_gcp_link.go b/internals/secrethub/service_gcp_link.go index 777f68cc..74022da3 100644 --- a/internals/secrethub/service_gcp_link.go +++ b/internals/secrethub/service_gcp_link.go @@ -146,6 +146,7 @@ func NewServiceGCPDeleteLinkCommand(io ui.IO, newClient newClientFunc) *ServiceG func (cmd *ServiceGCPDeleteLinkCommand) Register(r command.Registerer) { clause := r.Command("delete-link", "Delete the link between a SecretHub namespace and a GCP project.") + clause.HelpLong("After deleting the link you cannot create new GCP service accounts in the specified namespace and GCP project anymore. Exisiting service accounts will keep on working.") clause.Arg("namespace", "The SecretHub namespace to delete the link from.").Required().SetValue(&cmd.namespace) clause.Arg("project-id", "The GCP project to delete the link to.").Required().SetValue(&cmd.projectID) From a3f16135655b838e266922cda8b5736ddf30ec40 Mon Sep 17 00:00:00 2001 From: Simon Barendse Date: Fri, 3 Jul 2020 15:47:18 +0200 Subject: [PATCH 24/37] Fix typo "an" > "a" GCP service account --- internals/secrethub/service_gcp_init.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internals/secrethub/service_gcp_init.go b/internals/secrethub/service_gcp_init.go index dffc752d..0be37f6c 100644 --- a/internals/secrethub/service_gcp_init.go +++ b/internals/secrethub/service_gcp_init.go @@ -149,7 +149,7 @@ func (cmd *ServiceGCPInitCommand) Run() error { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *ServiceGCPInitCommand) Register(r command.Registerer) { - clause := r.Command("init", "Create a new service account that is tied to an GCP Service Account.") + clause := r.Command("init", "Create a new service account that is tied to a GCP Service Account.") clause.Arg("repo", "The service account is attached to the repository in this path.").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.repo) clause.Flag("kms-key", "The Resource ID of the KMS-key to be used for encrypting the service's account key.").StringVar(&cmd.kmsKeyResourceID) clause.Flag("service-account-email", "The email of the GCP Service Account that should have access to this service account.").StringVar(&cmd.serviceAccountEmail) From eb8c3c1f53e7ed47a8494f341cdedd5aa82a672b Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Fri, 3 Jul 2020 17:14:45 +0200 Subject: [PATCH 25/37] Update secrethub-go --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index eb14554e..e629ade1 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/pkg/errors v0.9.1 // indirect github.com/secrethub/demo-app v0.1.0 - github.com/secrethub/secrethub-go v0.29.1-0.20200703092019-9f5d3de9b0e4 + github.com/secrethub/secrethub-go v0.29.1-0.20200703150346-411544a71e9d github.com/zalando/go-keyring v0.0.0-20190208082241-fbe81aec3a07 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d diff --git a/go.sum b/go.sum index 51061109..d290f5fd 100644 --- a/go.sum +++ b/go.sum @@ -172,6 +172,8 @@ github.com/secrethub/secrethub-go v0.29.1-0.20200702114848-1a3657310d91 h1:10KZJ github.com/secrethub/secrethub-go v0.29.1-0.20200702114848-1a3657310d91/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= github.com/secrethub/secrethub-go v0.29.1-0.20200703092019-9f5d3de9b0e4 h1:TszZ+u/DRpPjaAGwEFSQNHkWhG4QR3KBxQJ66NfTAMk= github.com/secrethub/secrethub-go v0.29.1-0.20200703092019-9f5d3de9b0e4/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= +github.com/secrethub/secrethub-go v0.29.1-0.20200703150346-411544a71e9d h1:tADItWP+YXaGLD1ZMFocxDaKKVcu8wXgEulbcUmX4Ec= +github.com/secrethub/secrethub-go v0.29.1-0.20200703150346-411544a71e9d/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= From 54aa97d6eff19044d8cec84fbf41d331b41cc103 Mon Sep 17 00:00:00 2001 From: Simon Barendse Date: Mon, 6 Jul 2020 14:55:31 +0200 Subject: [PATCH 26/37] Do not accept a directory as argument to service init Just like we already do for `service aws init`, don't accept a directory as argument of the command. Instead, if you want to set a permission on a subdirectory, you should use the --permission flag. --- internals/secrethub/service_init.go | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/internals/secrethub/service_init.go b/internals/secrethub/service_init.go index 5a7698b7..93e6f718 100644 --- a/internals/secrethub/service_init.go +++ b/internals/secrethub/service_init.go @@ -23,7 +23,7 @@ type ServiceInitCommand struct { description string file string fileMode filemode.FileMode - path api.DirPath + repo api.RepoPath permission string clipper clip.Clipper io ui.IO @@ -54,25 +54,19 @@ func (cmd *ServiceInitCommand) Run() error { return ErrFlagsConflict("--clip and --file") } - repo := cmd.path.GetRepoPath() - client, err := cmd.newClient() if err != nil { return err } credential := credentials.CreateKey() - service, err := client.Services().Create(repo.Value(), cmd.description, credential) + service, err := client.Services().Create(cmd.repo.Value(), cmd.description, credential) if err != nil { return err } - if strings.Contains(cmd.permission, ":") && !cmd.path.IsRepoPath() { - return api.ErrInvalidRepoPath(cmd.path) - } - if cmd.permission != "" { - err = givePermission(service, cmd.path.GetRepoPath(), cmd.permission, client) + err = givePermission(service, cmd.repo, cmd.permission, client) if err != nil { return err } From 8b4889bdcd0699884ef8a870aff6ea70d6a47dea Mon Sep 17 00:00:00 2001 From: Floris van der Grinten Date: Mon, 6 Jul 2020 15:17:36 +0200 Subject: [PATCH 27/37] Move taken service account error to server --- internals/secrethub/service_aws_init.go | 5 +---- internals/secrethub/service_gcp_init.go | 4 +--- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/internals/secrethub/service_aws_init.go b/internals/secrethub/service_aws_init.go index 71bcf4ef..11ac5127 100644 --- a/internals/secrethub/service_aws_init.go +++ b/internals/secrethub/service_aws_init.go @@ -26,7 +26,6 @@ import ( // Errors var ( ErrInvalidAWSRegion = errMain.Code("invalid_region").Error("invalid AWS region") - ErrRoleAlreadyTaken = errMain.Code("role_taken").Error("a service account with that IAM role already exists. Use the existing service account by assuming the role and passing the --identity-provider=aws flag. Or create a new service account with a different IAM role.") ErrInvalidPermissionPath = errMain.Code("invalid_permission_path").ErrorPref("invalid permission path: %s") ErrMissingRegion = errMain.Code("missing_region").Error("could not find AWS region. Supply using the --region flag or in the AWS configuration. See https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html for the AWS configuration files") ) @@ -136,9 +135,7 @@ func (cmd *ServiceAWSInitCommand) Run() error { } service, err := client.Services().Create(cmd.repo.Value(), cmd.description, credentials.CreateAWS(cmd.kmsKeyID, cmd.role, cfg)) - if err == api.ErrCredentialAlreadyExists { - return ErrRoleAlreadyTaken - } else if err != nil { + if err != nil { return err } diff --git a/internals/secrethub/service_gcp_init.go b/internals/secrethub/service_gcp_init.go index 0be37f6c..018aac56 100644 --- a/internals/secrethub/service_gcp_init.go +++ b/internals/secrethub/service_gcp_init.go @@ -128,9 +128,7 @@ func (cmd *ServiceGCPInitCommand) Run() error { } service, err := client.Services().Create(cmd.repo.Value(), cmd.description, credentials.CreateGCPServiceAccount(cmd.serviceAccountEmail, cmd.kmsKeyResourceID)) - if err == api.ErrCredentialAlreadyExists { - return ErrRoleAlreadyTaken - } else if err != nil { + if err != nil { return err } From a8106cf1723b51893e3fb4ea48da940fb9f31e3e Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Mon, 6 Jul 2020 17:26:12 +0200 Subject: [PATCH 28/37] Directly check if repo exists This avoids an annoying error at the end if the repo does not exist. --- internals/secrethub/service_gcp_init.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/internals/secrethub/service_gcp_init.go b/internals/secrethub/service_gcp_init.go index 0be37f6c..195811c5 100644 --- a/internals/secrethub/service_gcp_init.go +++ b/internals/secrethub/service_gcp_init.go @@ -48,6 +48,11 @@ func (cmd *ServiceGCPInitCommand) Run() error { return err } + _, err = client.Repos().Get(cmd.repo.String()) + if err != nil { + return err + } + if cmd.serviceAccountEmail == "" && cmd.kmsKeyResourceID == "" { fmt.Fprintln(cmd.io.Stdout(), "This command creates a new service account for use on GCP. For help on this, run `secrethub service gcp init --help`.") From 0236dea47147de4c15da3988b3bf7eecfd9d80f5 Mon Sep 17 00:00:00 2001 From: Simon Barendse Date: Tue, 7 Jul 2020 12:09:49 +0200 Subject: [PATCH 29/37] Validate keyring input on gcp init --- internals/secrethub/service_gcp_init.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/internals/secrethub/service_gcp_init.go b/internals/secrethub/service_gcp_init.go index 018aac56..dabb66de 100644 --- a/internals/secrethub/service_gcp_init.go +++ b/internals/secrethub/service_gcp_init.go @@ -2,7 +2,9 @@ package secrethub import ( "context" + "errors" "fmt" + "regexp" "strings" "sync" "time" @@ -78,7 +80,7 @@ func (cmd *ServiceGCPInitCommand) Run() error { if err != nil { return err } - keyring, err := ui.ChooseDynamicOptions(cmd.io, "In which keyring is the KMS key you want to use for encrypting the service account's key?", kmsKeyLister.KeyringOptions, true, "keyring") + keyring, err := ui.ChooseDynamicOptionsValidate(cmd.io, "In which keyring is the KMS key you want to use for encrypting the service account's key?", kmsKeyLister.KeyringOptions, "keyring", validateGCPKeyring) if err != nil { return err } @@ -302,6 +304,13 @@ func (l *gcpKMSKeyOptionLister) KeyringOptions() ([]ui.Option, bool, error) { } } +func validateGCPKeyring(keyring string) error { + if !regexp.MustCompile("^projects/[a-zA-Z0-9-]*/locations/[a-zA-Z0-9-]*/keyRings/[a-zA-Z0-9-_]*$").MatchString(keyring) { + return errors.New("GCP keyring should be in the form \"projects//locations//keyRings/\"") + } + return nil +} + func (l *gcpKMSKeyOptionLister) KeyOptions(keyring string) func() ([]ui.Option, bool, error) { return func() ([]ui.Option, bool, error) { resp, err := l.kmsService.Projects.Locations.KeyRings.CryptoKeys.List(keyring).PageSize(10).Filter("purpose:ENCRYPT_DECRYPT").PageToken(l.nextPage).Do() From 0163ea04e39276e0ac4504025091d366909470bb Mon Sep 17 00:00:00 2001 From: Simon Barendse Date: Tue, 7 Jul 2020 12:18:15 +0200 Subject: [PATCH 30/37] Validate crypto key input on gcp init --- internals/secrethub/service_gcp_init.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/internals/secrethub/service_gcp_init.go b/internals/secrethub/service_gcp_init.go index dabb66de..8e318916 100644 --- a/internals/secrethub/service_gcp_init.go +++ b/internals/secrethub/service_gcp_init.go @@ -84,7 +84,7 @@ func (cmd *ServiceGCPInitCommand) Run() error { if err != nil { return err } - kmsKey, err := ui.ChooseDynamicOptions(cmd.io, "What is the KMS key you want to use for encrypting the service account's key?", kmsKeyLister.KeyOptions(keyring), true, "kms key") + kmsKey, err := ui.ChooseDynamicOptionsValidate(cmd.io, "What is the KMS key you want to use for encrypting the service account's key?", kmsKeyLister.KeyOptions(keyring), "kms key", validateGCPCryptoKey) if err != nil { return err } @@ -311,6 +311,13 @@ func validateGCPKeyring(keyring string) error { return nil } +func validateGCPCryptoKey(cryptoKey string) error { + if !regexp.MustCompile("^projects/[a-zA-Z0-9-]*/locations/[a-zA-Z0-9-]*/keyRings/[a-zA-Z0-9-_]*/cryptoKeys/[a-zA-Z0-9-_]*$").MatchString(cryptoKey) { + return errors.New("GCP crypto key should be in the form \"projects//locations//keyRings//cryptoKeys/\"") + } + return nil +} + func (l *gcpKMSKeyOptionLister) KeyOptions(keyring string) func() ([]ui.Option, bool, error) { return func() ([]ui.Option, bool, error) { resp, err := l.kmsService.Projects.Locations.KeyRings.CryptoKeys.List(keyring).PageSize(10).Filter("purpose:ENCRYPT_DECRYPT").PageToken(l.nextPage).Do() From 6958dd0a59a0144810ed8d109d929e26aa6c19f0 Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Tue, 7 Jul 2020 13:23:10 +0200 Subject: [PATCH 31/37] Only list user-managed Service Accounts Other Service Accounts are not supported anyway, so no reason to list them. --- internals/secrethub/service_gcp_init.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/internals/secrethub/service_gcp_init.go b/internals/secrethub/service_gcp_init.go index 018aac56..658a27a5 100644 --- a/internals/secrethub/service_gcp_init.go +++ b/internals/secrethub/service_gcp_init.go @@ -216,16 +216,19 @@ func (l *gcpServiceAccountOptionLister) Options() ([]ui.Option, bool, error) { return nil, false, gcp.HandleError(err) } - options := make([]ui.Option, len(resp.Accounts)) - for i, account := range resp.Accounts { + var options []ui.Option + for _, account := range resp.Accounts { + if err := api.ValidateGCPServiceAccountEmail(account.Email); err != nil { + continue + } display := account.Email if account.Description != "" { display += " (" + account.Description + ")" } - options[i] = ui.Option{ + options = append(options, ui.Option{ Value: account.Email, Display: display, - } + }) } l.nextPage = resp.NextPageToken From e5600ec12de0bfa5a5ec933514ed9059aa80d1b1 Mon Sep 17 00:00:00 2001 From: Simon Barendse Date: Tue, 7 Jul 2020 13:26:41 +0200 Subject: [PATCH 32/37] Verify components in GCP keyring and key are at least one char long Co-authored-by: Joris Coenen --- internals/secrethub/service_gcp_init.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internals/secrethub/service_gcp_init.go b/internals/secrethub/service_gcp_init.go index 8e318916..a2527c25 100644 --- a/internals/secrethub/service_gcp_init.go +++ b/internals/secrethub/service_gcp_init.go @@ -305,14 +305,14 @@ func (l *gcpKMSKeyOptionLister) KeyringOptions() ([]ui.Option, bool, error) { } func validateGCPKeyring(keyring string) error { - if !regexp.MustCompile("^projects/[a-zA-Z0-9-]*/locations/[a-zA-Z0-9-]*/keyRings/[a-zA-Z0-9-_]*$").MatchString(keyring) { + if !regexp.MustCompile("^projects/[a-zA-Z0-9-]+/locations/[a-zA-Z0-9-]+/keyRings/[a-zA-Z0-9-_]+$").MatchString(keyring) { return errors.New("GCP keyring should be in the form \"projects//locations//keyRings/\"") } return nil } func validateGCPCryptoKey(cryptoKey string) error { - if !regexp.MustCompile("^projects/[a-zA-Z0-9-]*/locations/[a-zA-Z0-9-]*/keyRings/[a-zA-Z0-9-_]*/cryptoKeys/[a-zA-Z0-9-_]*$").MatchString(cryptoKey) { + if !regexp.MustCompile("^projects/[a-zA-Z0-9-]+/locations/[a-zA-Z0-9-]+/keyRings/[a-zA-Z0-9-_]+/cryptoKeys/[a-zA-Z0-9-_]+$").MatchString(cryptoKey) { return errors.New("GCP crypto key should be in the form \"projects//locations//keyRings//cryptoKeys/\"") } return nil From 07d8c89dbc7c463a18e854f53d40b9e40ce61351 Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Tue, 7 Jul 2020 13:27:13 +0200 Subject: [PATCH 33/37] Fix build issue --- internals/secrethub/service_init.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internals/secrethub/service_init.go b/internals/secrethub/service_init.go index 93e6f718..3213526e 100644 --- a/internals/secrethub/service_init.go +++ b/internals/secrethub/service_init.go @@ -105,7 +105,7 @@ func (cmd *ServiceInitCommand) Run() error { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *ServiceInitCommand) Register(r command.Registerer) { clause := r.Command("init", "Create a new service account.") - clause.Arg("repo", "The service account is attached to the repository in this path.").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) + clause.Arg("repo", "The service account is attached to the repository in this path.").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.repo) clause.Flag("description", "A description for the service so others will recognize it.").StringVar(&cmd.description) clause.Flag("descr", "").Hidden().StringVar(&cmd.description) clause.Flag("desc", "").Hidden().StringVar(&cmd.description) From 86f3788db0b7684a0c4c633ee4c820e1d3d613d9 Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Tue, 7 Jul 2020 13:30:48 +0200 Subject: [PATCH 34/37] Preallocate slice with capacitiy --- internals/secrethub/service_gcp_init.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internals/secrethub/service_gcp_init.go b/internals/secrethub/service_gcp_init.go index 658a27a5..6f624eff 100644 --- a/internals/secrethub/service_gcp_init.go +++ b/internals/secrethub/service_gcp_init.go @@ -216,7 +216,7 @@ func (l *gcpServiceAccountOptionLister) Options() ([]ui.Option, bool, error) { return nil, false, gcp.HandleError(err) } - var options []ui.Option + options := make([]ui.Option, 0, len(resp.Accounts)) for _, account := range resp.Accounts { if err := api.ValidateGCPServiceAccountEmail(account.Email); err != nil { continue From d058990a98f1fce0bebce342b3f9331bbeab38fc Mon Sep 17 00:00:00 2001 From: Floris van der Grinten Date: Tue, 7 Jul 2020 15:24:27 +0200 Subject: [PATCH 35/37] Add comment to exists check Co-authored-by: Simon Barendse --- internals/secrethub/service_gcp_init.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internals/secrethub/service_gcp_init.go b/internals/secrethub/service_gcp_init.go index 195811c5..85952c2f 100644 --- a/internals/secrethub/service_gcp_init.go +++ b/internals/secrethub/service_gcp_init.go @@ -48,6 +48,7 @@ func (cmd *ServiceGCPInitCommand) Run() error { return err } + // Fail fast if the repo does not exist. _, err = client.Repos().Get(cmd.repo.String()) if err != nil { return err From 56f38ba917fa3f0b56f7a826af1a94819d7e8d0c Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Tue, 7 Jul 2020 17:54:51 +0200 Subject: [PATCH 36/37] Clarify filtering behaviour --- go.mod | 2 +- go.sum | 2 ++ internals/secrethub/service_gcp_init.go | 7 ++++--- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index e629ade1..1f7d9102 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/pkg/errors v0.9.1 // indirect github.com/secrethub/demo-app v0.1.0 - github.com/secrethub/secrethub-go v0.29.1-0.20200703150346-411544a71e9d + github.com/secrethub/secrethub-go v0.29.1-0.20200707154958-5e5602145597 github.com/zalando/go-keyring v0.0.0-20190208082241-fbe81aec3a07 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d diff --git a/go.sum b/go.sum index d290f5fd..ca493365 100644 --- a/go.sum +++ b/go.sum @@ -174,6 +174,8 @@ github.com/secrethub/secrethub-go v0.29.1-0.20200703092019-9f5d3de9b0e4 h1:TszZ+ github.com/secrethub/secrethub-go v0.29.1-0.20200703092019-9f5d3de9b0e4/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= github.com/secrethub/secrethub-go v0.29.1-0.20200703150346-411544a71e9d h1:tADItWP+YXaGLD1ZMFocxDaKKVcu8wXgEulbcUmX4Ec= github.com/secrethub/secrethub-go v0.29.1-0.20200703150346-411544a71e9d/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= +github.com/secrethub/secrethub-go v0.29.1-0.20200707154958-5e5602145597 h1:uC9ODMKaqBo1k8fxmFSWGkLr05TgEd3t4mHqJ8Jo9Gc= +github.com/secrethub/secrethub-go v0.29.1-0.20200707154958-5e5602145597/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= diff --git a/internals/secrethub/service_gcp_init.go b/internals/secrethub/service_gcp_init.go index 6f624eff..e8cd3a0c 100644 --- a/internals/secrethub/service_gcp_init.go +++ b/internals/secrethub/service_gcp_init.go @@ -68,7 +68,7 @@ func (cmd *ServiceGCPInitCommand) Run() error { serviceAccountLister := gcpServiceAccountOptionLister{ ProjectID: projectID, } - serviceAccountEmail, err := ui.ChooseDynamicOptionsValidate(cmd.io, "What is the email of the service account you want to use?", serviceAccountLister.Options, "service account", api.ValidateGCPServiceAccountEmail) + serviceAccountEmail, err := ui.ChooseDynamicOptionsValidate(cmd.io, "What is the email of the service account you want to use?", serviceAccountLister.Options, "service account", api.ValidateGCPUserManagedServiceAccountEmail) if err != nil { return err } @@ -90,7 +90,7 @@ func (cmd *ServiceGCPInitCommand) Run() error { } if cmd.serviceAccountEmail == "" { - serviceAccountEmail, err := ui.AskAndValidate(cmd.io, "What is the email of the GCP Service Account that should have access to the service?\n", 3, api.ValidateGCPServiceAccountEmail) + serviceAccountEmail, err := ui.AskAndValidate(cmd.io, "What is the email of the GCP Service Account that should have access to the service?\n", 3, api.ValidateGCPUserManagedServiceAccountEmail) if err != nil { return err } @@ -218,7 +218,8 @@ func (l *gcpServiceAccountOptionLister) Options() ([]ui.Option, bool, error) { options := make([]ui.Option, 0, len(resp.Accounts)) for _, account := range resp.Accounts { - if err := api.ValidateGCPServiceAccountEmail(account.Email); err != nil { + // Only list user-managed service accounts + if err := api.ValidateGCPUserManagedServiceAccountEmail(account.Email); err != nil { continue } display := account.Email From e081f471f4c3ab6d4892e7341095bd1b09f0aa2f Mon Sep 17 00:00:00 2001 From: Joris Coenen Date: Wed, 8 Jul 2020 11:37:12 +0200 Subject: [PATCH 37/37] Update secrethub-go to v0.30.0 --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 1f7d9102..227fefe6 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/pkg/errors v0.9.1 // indirect github.com/secrethub/demo-app v0.1.0 - github.com/secrethub/secrethub-go v0.29.1-0.20200707154958-5e5602145597 + github.com/secrethub/secrethub-go v0.30.0 github.com/zalando/go-keyring v0.0.0-20190208082241-fbe81aec3a07 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d diff --git a/go.sum b/go.sum index ca493365..4a4de5e0 100644 --- a/go.sum +++ b/go.sum @@ -176,6 +176,8 @@ github.com/secrethub/secrethub-go v0.29.1-0.20200703150346-411544a71e9d h1:tADIt github.com/secrethub/secrethub-go v0.29.1-0.20200703150346-411544a71e9d/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= github.com/secrethub/secrethub-go v0.29.1-0.20200707154958-5e5602145597 h1:uC9ODMKaqBo1k8fxmFSWGkLr05TgEd3t4mHqJ8Jo9Gc= github.com/secrethub/secrethub-go v0.29.1-0.20200707154958-5e5602145597/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= +github.com/secrethub/secrethub-go v0.30.0 h1:Nh1twPDwPbYQj/cYc1NG+j7sv76LZiXLPovyV83tZj0= +github.com/secrethub/secrethub-go v0.30.0/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=