From a27ef13b711857ad4652afa9ab3f31f009c65d77 Mon Sep 17 00:00:00 2001 From: Marwan Sulaiman Date: Mon, 25 Feb 2019 16:59:00 -0500 Subject: [PATCH] storage/gcp: allow json key to be used for GCS access (#1088) --- config.dev.toml | 10 ++++++++++ go.mod | 2 +- pkg/config/gcp.go | 1 + pkg/storage/gcp/gcp.go | 13 ++++++++++++- 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/config.dev.toml b/config.dev.toml index 7574f847..f918a80f 100755 --- a/config.dev.toml +++ b/config.dev.toml @@ -182,6 +182,16 @@ SingleFlightType = "memory" # Env override: ATHENS_STORAGE_GCP_BUCKET Bucket = "MY_GCP_BUCKET" + # JSONKey allows Athens to be run outside of GCP + # but still be able to access GCS. If you are + # running Athens inside GCP, you will most + # likely not need this as GCP figures out + # internal authentication between products for you. + # Pro tip: if you are pasting this as a JSON inside a string, + # make sure you escape "\n" by making it "\\n". + # Env override: ATHENS_STORAGE_GCP_JSON_KEY + JSONKey = "SERVICE_ACCOUNT_KEY" + [Storage.Minio] # Endpoint for Minio storage # Env override: ATHENS_MINIO_ENDPOINT diff --git a/go.mod b/go.mod index 827a5836..6a57bd51 100644 --- a/go.mod +++ b/go.mod @@ -40,7 +40,7 @@ require ( go.opencensus.io v0.17.0 golang.org/x/crypto v0.0.0-20181029103014-dab2b1051b5d // indirect golang.org/x/net v0.0.0-20181029044818-c44066c5c816 // indirect - golang.org/x/oauth2 v0.0.0-20180620175406-ef147856a6dd // indirect + golang.org/x/oauth2 v0.0.0-20180620175406-ef147856a6dd golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f golang.org/x/sys v0.0.0-20181031143558-9b800f95dbbc // indirect google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf diff --git a/pkg/config/gcp.go b/pkg/config/gcp.go index 7b1bd47d..36321a12 100644 --- a/pkg/config/gcp.go +++ b/pkg/config/gcp.go @@ -4,4 +4,5 @@ package config type GCPConfig struct { ProjectID string `envconfig:"GOOGLE_CLOUD_PROJECT"` Bucket string `validate:"required" envconfig:"ATHENS_STORAGE_GCP_BUCKET"` + JSONKey string `envconfig:"ATHENS_STORAGE_GCP_JSON_KEY"` } diff --git a/pkg/storage/gcp/gcp.go b/pkg/storage/gcp/gcp.go index 14162ab0..b6c6b592 100644 --- a/pkg/storage/gcp/gcp.go +++ b/pkg/storage/gcp/gcp.go @@ -8,6 +8,8 @@ import ( "cloud.google.com/go/storage" "github.com/gomods/athens/pkg/config" "github.com/gomods/athens/pkg/errors" + "golang.org/x/oauth2/google" + "google.golang.org/api/option" ) // Storage implements the (./pkg/storage).Backend interface @@ -26,7 +28,16 @@ type Storage struct { // See https://cloud.google.com/docs/authentication/getting-started. func New(ctx context.Context, gcpConf *config.GCPConfig, timeout time.Duration) (*Storage, error) { const op errors.Op = "gcp.New" - s, err := storage.NewClient(ctx) + + opts := []option.ClientOption{} + if gcpConf.JSONKey != "" { + creds, err := google.CredentialsFromJSON(ctx, []byte(gcpConf.JSONKey), storage.ScopeReadWrite) + if err != nil { + return nil, errors.E(op, fmt.Errorf("could not get GCS credentials: %v", err)) + } + opts = append(opts, option.WithCredentials(creds)) + } + s, err := storage.NewClient(ctx, opts...) if err != nil { return nil, errors.E(op, fmt.Errorf("could not create new storage client: %s", err)) }