feat: add impersonation support to gcs client (#810)

rkapoor10-patch-1
Akhilesh Pandey 2023-11-17 21:15:05 +00:00 committed by Harness
parent f3bfdeaf8e
commit 00a69152d7
4 changed files with 31 additions and 9 deletions

View File

@ -22,7 +22,9 @@ const (
)
type Config struct {
Provider Provider
Bucket string
KeyPath string
Provider Provider
Bucket string
KeyPath string
TargetPrincipal string
ImpersonationLifetime int
}

View File

@ -23,9 +23,13 @@ import (
"cloud.google.com/go/storage"
"github.com/rs/zerolog/log"
"google.golang.org/api/impersonate"
"google.golang.org/api/option"
)
// scopes best practice: https://cloud.google.com/compute/docs/access/service-accounts#scopes_best_practice
const defaultScope = "https://www.googleapis.com/auth/cloud-platform"
type GCSStore struct {
// Bucket is the name of the GCS bucket to use.
bucket string
@ -45,11 +49,20 @@ func NewGCSStore(cfg Config) (Store, error) {
}, nil
}
// Use workload identity default credentials (GKE environment)
client, err := storage.NewClient(context.Background())
// Use workload identity impersonation default credentials (GKE environment)
ts, err := impersonate.CredentialsTokenSource(context.Background(), impersonate.CredentialsConfig{
TargetPrincipal: cfg.TargetPrincipal,
Scopes: []string{defaultScope}, // Required field
Lifetime: time.Duration(cfg.ImpersonationLifetime) * time.Hour,
})
if err != nil {
return nil, fmt.Errorf("failed to create GCS client with workload identity or default credentials: %w", err)
return nil, fmt.Errorf("failed to impersonate the client service account %s : %w", cfg.TargetPrincipal, err)
}
client, err := storage.NewClient(context.Background(), option.WithTokenSource(ts))
if err != nil {
return nil, fmt.Errorf("failed to create GCS client with workload identity impersonation: %w", err)
}
return &GCSStore{
bucket: cfg.Bucket,
client: client,

View File

@ -247,9 +247,11 @@ func ProvideBlobStoreConfig(config *types.Config) (blob.Config, error) {
config.BlobStore.Bucket = filepath.Join(homedir, gitnessHomeDir, blobDir)
}
return blob.Config{
Provider: config.BlobStore.Provider,
Bucket: config.BlobStore.Bucket,
KeyPath: config.BlobStore.KeyPath,
Provider: config.BlobStore.Provider,
Bucket: config.BlobStore.Bucket,
KeyPath: config.BlobStore.KeyPath,
TargetPrincipal: config.BlobStore.TargetPrincipal,
ImpersonationLifetime: config.BlobStore.ImpersonationLifetime,
}, nil
}

View File

@ -155,6 +155,11 @@ type Config struct {
// In case of GCS provider, this is expected to be the path to the service account key file.
KeyPath string `envconfig:"GITNESS_BLOBSTORE_KEY_PATH" default:""`
// Email ID of the google service account that needs to be impersonated
TargetPrincipal string `envconfig:"GITNESS_BLOBSTORE_TARGET_PRINCIPAL" default:""`
ImpersonationLifetime int `envconfig:"GITNESS_BLOBSTORE_IMPERSONATION_LIFETIME" default:"12"`
}
// Token defines token configuration parameters.