github.com/myhau/pulumi/pkg/v3@v3.70.2-0.20221116134521-f2775972e587/authhelpers/gcpauth.go (about) 1 package authhelpers 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "os" 8 9 "cloud.google.com/go/storage" 10 "golang.org/x/oauth2/google" 11 12 "gocloud.dev/blob/gcsblob" 13 14 "gocloud.dev/blob" 15 "gocloud.dev/gcp" 16 ) 17 18 type GoogleCredentials struct { 19 PrivateKeyID string `json:"private_key_id"` 20 PrivateKey string `json:"private_key"` 21 ClientEmail string `json:"client_email"` 22 ClientID string `json:"client_id"` 23 } 24 25 // ResolveGoogleCredentials loads the google credentials using the pulumi-specific 26 // logic first, falling back to the DefaultCredentials resoulution after. 27 func ResolveGoogleCredentials(ctx context.Context, scope string) (*google.Credentials, error) { 28 // GOOGLE_CREDENTIALS aren't part of the gcloud standard authorization variables 29 // but the GCP terraform provider uses this variable to allow users to authenticate 30 // with the contents of a credentials.json file instead of just a file path. 31 // https://www.terraform.io/docs/backends/types/gcs.html 32 if creds := os.Getenv("GOOGLE_CREDENTIALS"); creds != "" { 33 // We try $GOOGLE_CREDENTIALS before gcp.DefaultCredentials 34 // so that users can override the default creds 35 credentials, err := google.CredentialsFromJSON(ctx, []byte(creds), scope) 36 if err != nil { 37 return nil, fmt.Errorf("unable to parse credentials from $GOOGLE_CREDENTIALS: %w", err) 38 } 39 return credentials, nil 40 } 41 42 // DefaultCredentials will attempt to load creds in the following order: 43 // 1. a file located at $GOOGLE_APPLICATION_CREDENTIALS 44 // 2. application_default_credentials.json file in ~/.config/gcloud or $APPDATA\gcloud 45 credentials, err := gcp.DefaultCredentials(ctx) 46 if err != nil { 47 return nil, fmt.Errorf("unable to find gcp credentials: %w", err) 48 } 49 return credentials, nil 50 } 51 52 func GoogleCredentialsMux(ctx context.Context) (*blob.URLMux, error) { 53 credentials, err := ResolveGoogleCredentials(ctx, storage.ScopeReadWrite) 54 if err != nil { 55 return nil, fmt.Errorf("missing google credentials: %w", err) 56 } 57 58 client, err := gcp.NewHTTPClient(gcp.DefaultTransport(), credentials.TokenSource) 59 if err != nil { 60 return nil, err 61 } 62 63 options := gcsblob.Options{} 64 account := GoogleCredentials{} 65 err = json.Unmarshal(credentials.JSON, &account) 66 if err == nil && account.ClientEmail != "" && account.PrivateKey != "" { 67 options.GoogleAccessID = account.ClientEmail 68 options.PrivateKey = []byte(account.PrivateKey) 69 } 70 71 blobmux := &blob.URLMux{} 72 blobmux.RegisterBucket(gcsblob.Scheme, &gcsblob.URLOpener{ 73 Client: client, 74 Options: options, 75 }) 76 77 return blobmux, nil 78 }