Skip to content

Commit

Permalink
Backport of Update gcp-common/IAM Credentials API usage into release/…
Browse files Browse the repository at this point in the history
…vault-1.5.x (#112)

* backport of commit 4f30655

* backport of commit 73a8830

* backport of commit 802bd7f

* backport of commit 502cbef

* backport of commit 6d8fb90

* backport of commit b55c219

* backport of commit 709cc9d

* backport of commit 3962020

* backport of commit ac07c84

* backport of commit d4f053b

* backport of commit 84ce3e9

* backport of commit ce432e2

* backport of commit 633d077

* backport of commit bd185bd

Co-authored-by: catsby <clint@ctshryock.com>
  • Loading branch information
1 parent 9b39891 commit 80d0f15
Show file tree
Hide file tree
Showing 12 changed files with 2,029 additions and 52 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ testcompile: fmtcheck generate
done

test:
@go test -short -parallel=40 ./...
@go test -short -parallel=40 ./... $(TESTARGS)

test-acc:
@go test -parallel=40 $(TESTARGS)
@go test -parallel=40 $(TEST) $(TESTARGS)
# generate runs `go generate` to build the dynamically generated
# source files.
generate:
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ require (
github.com/golang/mock v1.4.3
github.com/hashicorp/errwrap v1.0.0
github.com/hashicorp/go-cleanhttp v0.5.1
github.com/hashicorp/go-gcp-common v0.6.0
github.com/hashicorp/go-gcp-common v0.7.0
github.com/hashicorp/go-hclog v0.12.0
github.com/hashicorp/go-uuid v1.0.2
github.com/hashicorp/vault/api v1.0.5-0.20200215224050-f6547fa8e820
Expand Down
13 changes: 4 additions & 9 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekf
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
Expand All @@ -63,8 +62,10 @@ github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-gcp-common v0.6.0 h1:m1X+DK003bj4WEjqOnv+Csepb3zpfN/bidboUeUSj68=
github.com/hashicorp/go-gcp-common v0.6.0/go.mod h1:RuZi18562/z30wxOzpjeRrGcmk9Ro/rBzixaSZDhIhY=
github.com/hashicorp/go-gcp-common v0.6.1-0.20210426170025-7128e4e85038 h1:yl5Y17dL+V6vSj32Yd2R6x0+euvdhUOpbuVqH9bV+LU=
github.com/hashicorp/go-gcp-common v0.6.1-0.20210426170025-7128e4e85038/go.mod h1:RuZi18562/z30wxOzpjeRrGcmk9Ro/rBzixaSZDhIhY=
github.com/hashicorp/go-gcp-common v0.7.0 h1:DF2liDG2N71MYt5SN0FJRPdBjxeqx9wfM/PnF7a8Fqk=
github.com/hashicorp/go-gcp-common v0.7.0/go.mod h1:RuZi18562/z30wxOzpjeRrGcmk9Ro/rBzixaSZDhIhY=
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-hclog v0.12.0 h1:d4QkX8FRTYaKaCZBoXYY8zJX2BXjWxurN/GA2tkrmZM=
Expand Down Expand Up @@ -96,7 +97,6 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/vault/api v1.0.5-0.20200215224050-f6547fa8e820 h1:biZidYDDEWnuOI9mXnJre8lwHKhb5ym85aSXk3oz/dc=
github.com/hashicorp/vault/api v1.0.5-0.20200215224050-f6547fa8e820/go.mod h1:3f12BMfgDGjTsTtIUj+ZKZwSobQpZtYGFIEehOv5z1o=
github.com/hashicorp/vault/sdk v0.1.14-0.20200215195600-2ca765f0a500 h1:tiMX2ewq4ble+e2zENzBvaH2dMoFHe80NbnrF5Ir9Kk=
github.com/hashicorp/vault/sdk v0.1.14-0.20200215195600-2ca765f0a500/go.mod h1:WX57W2PwkrOPQ6rVQk+dy5/htHIaB4aBM70EwKThu10=
github.com/hashicorp/vault/sdk v0.1.14-0.20200427170607-03332aaf8d18 h1:xnQPngs9nbaMNx7keJMa1ccVAvs97ZHTno9o1Iz5x8Y=
github.com/hashicorp/vault/sdk v0.1.14-0.20200427170607-03332aaf8d18/go.mod h1:WX57W2PwkrOPQ6rVQk+dy5/htHIaB4aBM70EwKThu10=
Expand Down Expand Up @@ -170,7 +170,6 @@ go.opencensus.io v0.19.2/go.mod h1:NO/8qkisMZLZ1FCsKNqtJPwc8/TaclWyY0B6wcYNg9M=
go.opencensus.io v0.20.1 h1:pMEjRZ1M4ebWGikflH7nQpV6+Zr88KBMA2XJD3sbijw=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480 h1:O5YqonU5IWby+w98jVUG9h7zlCWCcH4RHyPVReBmhzk=
golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
Expand Down Expand Up @@ -214,7 +213,6 @@ golang.org/x/sys v0.0.0-20181218192612-074acd46bca6/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e h1:nFYrTHrdrAOpShe27kaFHjsqYSEQ0KWqdWLu3xuZJts=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be h1:QAcqgptGM8IQBC9K/RC4o+O9YmqEm0diQn9QmZw/0mU=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand All @@ -232,7 +230,6 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135 h1:5Beo0mZN8dRzgrMMkDp0jc8YXQKx9DiJ2k1dkvGsn5A=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
google.golang.org/api v0.0.0-20181220000619-583d854617af/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.2.0/go.mod h1:IfRCZScioGtypHNTlz3gFk67J8uePVW7uDTBzXuIkhU=
Expand Down Expand Up @@ -268,7 +265,5 @@ honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
rsc.io/quote/v3 v3.1.0 h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
47 changes: 41 additions & 6 deletions plugin/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,12 @@ import (
"google.golang.org/api/cloudresourcemanager/v1"
"google.golang.org/api/compute/v1"
"google.golang.org/api/iam/v1"
"google.golang.org/api/iamcredentials/v1"
)

var (
// cacheTime is the duration for which to cache clients and credentials. This
// must be less than 60 minutes.
cacheTime = 30 * time.Minute
)
// cacheTime is the duration for which to cache clients and credentials. This
// must be less than 60 minutes.
var cacheTime = 30 * time.Minute

type GcpAuthBackend struct {
*framework.Backend
Expand Down Expand Up @@ -71,7 +70,14 @@ func Backend() *GcpAuthBackend {
return b
}

// IAMClient returns a new IAM client. The client is cached.
// IAMClient returns a new IAM client. This client talks to the IAM endpoint,
// for all things that are not signing JWTs. The SignJWT method in the IAM
// client has been deprecated, but other methods are still valid and supported.
//
// See: https://pkg.go.dev/google.golang.org/api@v0.45.0/iam/v1 and:
// https://cloud.google.com/iam/docs/migrating-to-credentials-api#iam-sign-jwt-go
//
// The client is cached.
func (b *GcpAuthBackend) IAMClient(s logical.Storage) (*iam.Service, error) {
httpClient, err := b.httpClient(s)
if err != nil {
Expand All @@ -94,6 +100,35 @@ func (b *GcpAuthBackend) IAMClient(s logical.Storage) (*iam.Service, error) {
return client.(*iam.Service), nil
}

// IAMCredentialsClient returns a new IAM Service Account Credentials client.
// This client talks to the IAM Service Credentials endpoint, for signing JWTs.
//
// See:
// https://pkg.go.dev/google.golang.org/api@v0.45.0/iamcredentials/v1#pkg-overview
//
// The client is cached.
func (b *GcpAuthBackend) IAMCredentialsClient(s logical.Storage) (*iamcredentials.Service, error) {
httpClient, err := b.httpClient(s)
if err != nil {
return nil, errwrap.Wrapf("failed to create IAM Service Account Credentials HTTP client: {{err}}", err)
}

client, err := b.cache.Fetch("iamcredentials", cacheTime, func() (interface{}, error) {
client, err := iamcredentials.New(httpClient)
if err != nil {
return nil, errwrap.Wrapf("failed to create IAM Service Account Credentials client: {{err}}", err)
}
client.UserAgent = useragent.String()

return client, nil
})
if err != nil {
return nil, err
}

return client.(*iamcredentials.Service), nil
}

// ComputeClient returns a new Compute client. The client is cached.
func (b *GcpAuthBackend) ComputeClient(s logical.Storage) (*compute.Service, error) {
httpClient, err := b.httpClient(s)
Expand Down
31 changes: 9 additions & 22 deletions plugin/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,23 @@ import (
"encoding/json"
"errors"
"fmt"
"strings"
"time"

"github.com/hashicorp/go-cleanhttp"
"github.com/hashicorp/go-gcp-common/gcputil"
"github.com/hashicorp/vault/api"
"github.com/hashicorp/vault/sdk/helper/parseutil"
"golang.org/x/oauth2"
"google.golang.org/api/iam/v1"
"strings"
"time"
"google.golang.org/api/iamcredentials/v1"
)

type CLIHandler struct{}

func getSignedJwt(role string, m map[string]string) (string, error) {
ctx := context.WithValue(context.Background(), oauth2.HTTPClient, cleanhttp.DefaultClient())

credentials, tokenSource, err := gcputil.FindCredentials(m["credentials"], ctx, iam.CloudPlatformScope)
credentials, tokenSource, err := gcputil.FindCredentials(m["credentials"], ctx, iamcredentials.CloudPlatformScope)
if err != nil {
return "", fmt.Errorf("could not obtain credentials: %v", err)
}
Expand All @@ -35,16 +36,7 @@ func getSignedJwt(role string, m map[string]string) (string, error) {
return "", errors.New("could not obtain service account from credentials (are you using Application Default Credentials?). You must provide a service account to authenticate as")
}

project, ok := m["project"]
if !ok {
if credentials != nil {
project = credentials.ProjectId
} else {
project = "-"
}
}

var ttl = time.Duration(defaultIamMaxJwtExpMinutes) * time.Minute
ttl := time.Duration(defaultIamMaxJwtExpMinutes) * time.Minute
jwtExpStr, ok := m["jwt_exp"]
if ok {
ttl, err = parseutil.ParseDurationSecond(jwtExpStr)
Expand All @@ -63,16 +55,16 @@ func getSignedJwt(role string, m map[string]string) (string, error) {
return "", fmt.Errorf("could not convert JWT payload to JSON string: %v", err)
}

jwtReq := &iam.SignJwtRequest{
jwtReq := &iamcredentials.SignJwtRequest{
Payload: string(payloadBytes),
}

iamClient, err := iam.New(httpClient)
iamClient, err := iamcredentials.New(httpClient)
if err != nil {
return "", fmt.Errorf("could not create IAM client: %v", err)
}

resourceName := fmt.Sprintf("projects/%s/serviceAccounts/%s", project, serviceAccount)
resourceName := fmt.Sprintf(gcputil.ServiceAccountCredentialsTemplate, serviceAccount)
resp, err := iamClient.Projects.ServiceAccounts.SignJwt(resourceName, jwtReq).Do()
if err != nil {
return "", fmt.Errorf("unable to sign JWT for %s using given Vault credentials: %v", resourceName, err)
Expand Down Expand Up @@ -104,7 +96,6 @@ func (h *CLIHandler) Auth(c *api.Client, m map[string]string) (*api.Secret, erro
"role": role,
"jwt": loginToken,
})

if err != nil {
return nil, err
}
Expand Down Expand Up @@ -161,10 +152,6 @@ Configuration:
"client_email" if "credentials" specified and this value is not.
The actual credential must have the "iam.serviceAccounts.signJWT"
permissions on this service account.
project=<string>
Project for the service account who will be authenticating to Vault.
Defaults to the credential's "project_id" (if credentials are specified)."
`

return strings.TrimSpace(help)
Expand Down
12 changes: 6 additions & 6 deletions plugin/login_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ package gcpauth
import (
"encoding/json"
"fmt"
"github.com/hashicorp/go-gcp-common/gcputil"
"google.golang.org/api/iam/v1"
"time"

"github.com/hashicorp/go-gcp-common/gcputil"
"google.golang.org/api/iamcredentials/v1"
)

func ServiceAccountLoginJwt(
iamClient *iam.Service, exp time.Time, aud, project, serviceAccount string) (*iam.SignJwtResponse, error) {
accountResource := fmt.Sprintf(gcputil.ServiceAccountTemplate, project, serviceAccount)
func ServiceAccountLoginJwt(iamClient *iamcredentials.Service, exp time.Time, aud, serviceAccount string) (*iamcredentials.SignJwtResponse, error) {
accountResource := fmt.Sprintf(gcputil.ServiceAccountCredentialsTemplate, serviceAccount)

payload, err := json.Marshal(map[string]interface{}{
"sub": serviceAccount,
Expand All @@ -20,7 +20,7 @@ func ServiceAccountLoginJwt(
if err != nil {
return nil, err
}
jwtReq := &iam.SignJwtRequest{
jwtReq := &iamcredentials.SignJwtRequest{
Payload: string(payload),
}
return iamClient.Projects.ServiceAccounts.SignJwt(accountResource, jwtReq).Do()
Expand Down
4 changes: 2 additions & 2 deletions plugin/path_login_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,12 +178,12 @@ func TestLogin_IAM(t *testing.T) {
}

// Build the JWT token
iamClient, err := b.IAMClient(storage)
iamClient, err := b.IAMCredentialsClient(storage)
if err != nil {
t.Fatal(err)
}
exp := time.Now().Add(10 * time.Minute)
jwt, err := ServiceAccountLoginJwt(iamClient, exp, "vault/"+role, creds.ProjectId, creds.ClientEmail)
jwt, err := ServiceAccountLoginJwt(iamClient, exp, "vault/"+role, creds.ClientEmail)
if err != nil {
t.Fatal(err)
}
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 80d0f15

Please sign in to comment.