From e396d87bc5f084fa8189046404731ddd9a6cbdc5 Mon Sep 17 00:00:00 2001 From: stephan stachurski Date: Wed, 30 Aug 2017 15:42:02 -0400 Subject: [PATCH] add support to use application default credentials to gcs storage backend (#3257) --- physical/gcs/gcs.go | 43 ++++++++++++------- .../storage/google-cloud.html.md | 7 +-- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/physical/gcs/gcs.go b/physical/gcs/gcs.go index 27125b471..5e7fc78cb 100644 --- a/physical/gcs/gcs.go +++ b/physical/gcs/gcs.go @@ -42,26 +42,14 @@ func NewGCSBackend(conf map[string]string, logger log.Logger) (physical.Backend, } } - // path to service account JSON file - credentialsFile := os.Getenv("GOOGLE_APPLICATION_CREDENTIALS") - if credentialsFile == "" { - credentialsFile = conf["credentials_file"] - if credentialsFile == "" { - return nil, fmt.Errorf("env var GOOGLE_APPLICATION_CREDENTIALS or configuration parameter 'credentials_file' must be set") - } - } - - client, err := storage.NewClient( - context.Background(), - option.WithServiceAccountFile(credentialsFile), - ) - + ctx := context.Background() + client, err := newGCSClient(ctx, conf, logger) if err != nil { - return nil, fmt.Errorf("error establishing storage client: '%v'", err) + return nil, errwrap.Wrapf("error establishing strorage client: {{err}}", err) } // check client connectivity by getting bucket attributes - _, err = client.Bucket(bucketName).Attrs(context.Background()) + _, err = client.Bucket(bucketName).Attrs(ctx) if err != nil { return nil, fmt.Errorf("unable to access bucket '%s': '%v'", bucketName, err) } @@ -88,6 +76,29 @@ func NewGCSBackend(conf map[string]string, logger log.Logger) (physical.Backend, return &g, nil } +func newGCSClient(ctx context.Context, conf map[string]string, logger log.Logger) (*storage.Client, error) { + // if credentials_file is configured, try to use it + // else use application default credentials + credentialsFile, ok := conf["credentials_file"] + if ok { + client, err := storage.NewClient( + ctx, + option.WithServiceAccountFile(credentialsFile), + ) + + if err != nil { + return nil, fmt.Errorf("error with provided credentials: '%v'", err) + } + return client, nil + } + + client, err := storage.NewClient(ctx) + if err != nil { + return nil, errwrap.Wrapf("error with application default credentials: {{err}}", err) + } + return client, nil +} + // Put is used to insert or update an entry func (g *GCSBackend) Put(entry *physical.Entry) error { defer metrics.MeasureSince([]string{"gcs", "put"}, time.Now()) diff --git a/website/source/docs/configuration/storage/google-cloud.html.md b/website/source/docs/configuration/storage/google-cloud.html.md index d17ac9c25..2e6a98b66 100644 --- a/website/source/docs/configuration/storage/google-cloud.html.md +++ b/website/source/docs/configuration/storage/google-cloud.html.md @@ -34,10 +34,10 @@ storage "gcs" { account must have permission to read, write, and delete from the bucket. This can also be provided via the environment variable `GOOGLE_STORAGE_BUCKET`. -- `credentials_file` `(string: )` – Specifies the path on disk to a +- `credentials_file` `(string: "")` – Specifies the path on disk to a Google Cloud Platform [service account][gcs-service-account] private key file - in [JSON format][gcs-private-key]. This can also be provided via the - environment variable `GOOGLE_APPLICATION_CREDENTIALS`. + in [JSON format][gcs-private-key]. The GCS client library will attempt to use + the [application default credentials][adc] if this is not specified. - `max_parallel` `(string: "128")` – Specifies the maximum number of concurrent requests. @@ -55,6 +55,7 @@ storage "gcs" { } ``` +[adc]: https://developers.google.com/identity/protocols/application-default-credentials [gcs]: https://cloud.google.com/storage/ [gcs-service-account]: https://cloud.google.com/compute/docs/access/service-accounts [gcs-private-key]: https://cloud.google.com/storage/docs/authentication#generating-a-private-key