Skip to content

Commit

Permalink
Update api version
Browse files Browse the repository at this point in the history
  • Loading branch information
digivava committed Oct 26, 2021
1 parent 23859a1 commit 1ef3949
Show file tree
Hide file tree
Showing 8 changed files with 963 additions and 5 deletions.
2 changes: 1 addition & 1 deletion api/auth/approle/go.mod
Expand Up @@ -4,4 +4,4 @@ go 1.16

replace github.com/hashicorp/vault/api => ../../../api

require github.com/hashicorp/vault/api v1.1.1
require github.com/hashicorp/vault/api v1.2.0
2 changes: 1 addition & 1 deletion api/auth/aws/go.mod
Expand Up @@ -9,5 +9,5 @@ require (
github.com/hashicorp/go-hclog v0.16.2
github.com/hashicorp/go-secure-stdlib/awsutil v0.1.6
github.com/hashicorp/go-uuid v1.0.2
github.com/hashicorp/vault/api v1.1.1
github.com/hashicorp/vault/api v1.2.0
)
3 changes: 2 additions & 1 deletion api/auth/aws/go.sum
Expand Up @@ -190,8 +190,9 @@ github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdI
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo=
github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
Expand Down
139 changes: 139 additions & 0 deletions api/auth/gcp/gcp.go
@@ -0,0 +1,139 @@
package gcp

import (
"context"
"encoding/json"
"fmt"
"time"

"cloud.google.com/go/compute/metadata"
credentials "cloud.google.com/go/iam/credentials/apiv1"
"github.com/hashicorp/vault/api"
credentialspb "google.golang.org/genproto/googleapis/iam/credentials/v1"
)

type GCPAuth struct {
roleName string
mountPath string
authType string
serviceAccountEmail string
}

var _ api.AuthMethod = (*GCPAuth)(nil)

type LoginOption func(a *GCPAuth) error

const (
iamType = "iam"
gceType = "gce"
defaultMountPath = "gcp"
defaultAuthType = gceType
)

// NewGCPAuth initializes a new GCP auth method interface to be
// passed as a parameter to the client.Auth().Login method.
//
// Supported options: WithMountPath, WithIAMAuth
func NewGCPAuth(roleName string, opts ...LoginOption) (*GCPAuth, error) {
if roleName == "" {
return nil, fmt.Errorf("no role name provided for login")
}

a := &GCPAuth{
mountPath: defaultMountPath,
authType: defaultAuthType,
roleName: roleName,
}

// Loop through each option
for _, opt := range opts {
// Call the option giving the instantiated
// *GCPAuth as the argument
err := opt(a)
if err != nil {
return nil, fmt.Errorf("error with login option: %w", err)
}
}

// return the modified auth struct instance
return a, nil
}

// Login sets up the required request body for the GCP auth method's /login
// endpoint, and performs a write to it. This method defaults to the "gce"
// auth type unless NewGCPAuth is called with WithIAMAuth().
func (a *GCPAuth) Login(ctx context.Context, client *api.Client) (*api.Secret, error) {
loginData := map[string]interface{}{
"role": a.roleName,
}
switch a.authType {
case gceType:
if !metadata.OnGCE() {
return nil, fmt.Errorf("GCE metadata service not available")
}
// loginData["jwt"] =
case iamType:
jwtResp, err := a.signJWT()
if err != nil {
return nil, fmt.Errorf("unable to sign JWT for authenticating to GCP: %w", err)
}
loginData["jwt"] = jwtResp.SignedJwt
}

path := fmt.Sprintf("auth/%s/login", a.mountPath)
resp, err := client.Logical().Write(path, loginData)
if err != nil {
return nil, fmt.Errorf("unable to log in with GCP auth: %w", err)
}

return resp, nil
}

func WithMountPath(mountPath string) LoginOption {
return func(a *GCPAuth) error {
a.mountPath = mountPath
return nil
}
}

func WithIAMAuth(serviceAccountEmail string) LoginOption {
return func(a *GCPAuth) error {
a.serviceAccountEmail = serviceAccountEmail
a.authType = iamType
return nil
}
}

// generate signed JWT token from GCP IAM.
func (a *GCPAuth) signJWT() (*credentialspb.SignJwtResponse, error) {
ctx := context.Background()
iamClient, err := credentials.NewIamCredentialsClient(ctx) // can pass option.WithCredentialsFile("path/to/creds.json") as second param if GOOGLE_APPLICATION_CREDENTIALS env var not set
if err != nil {
return nil, fmt.Errorf("unable to initialize IAM credentials client: %w", err)
}
defer iamClient.Close()

resourceName := fmt.Sprintf("projects/-/serviceAccounts/%s", a.serviceAccountEmail)
jwtPayload := map[string]interface{}{
"aud": fmt.Sprintf("vault/%s", a.roleName),
"sub": a.serviceAccountEmail,
"exp": time.Now().Add(time.Minute * 10).Unix(),
}

payloadBytes, err := json.Marshal(jwtPayload)
if err != nil {
return nil, fmt.Errorf("unable to marshal jwt payload to json: %w", err)
}

signJWTReq := &credentialspb.SignJwtRequest{
Name: resourceName,
Payload: string(payloadBytes),
}

jwtResp, err := iamClient.SignJwt(ctx, signJWTReq)
if err != nil {
return nil, fmt.Errorf("unable to sign JWT: %w", err)
}

return jwtResp, nil
}
11 changes: 11 additions & 0 deletions api/auth/gcp/go.mod
@@ -0,0 +1,11 @@
module github.com/hashicorp/vault/api/auth/gcp

go 1.16

replace github.com/hashicorp/vault/api => ../../../api

require (
cloud.google.com/go v0.97.0
github.com/hashicorp/vault/api v1.2.0
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0
)

0 comments on commit 1ef3949

Please sign in to comment.