go-cloud icon indicating copy to clipboard operation
go-cloud copied to clipboard

Be able to OpenPostgresURL with a provided Credential JSON rather than forced to use files

Open suleimi opened this issue 3 years ago • 4 comments

Hi!

I have a use case where i would like to be able to Open a PostgresURL connection via the gcppostgres package using a google credential (JSON) of my choice. Currently I am limited to OpenPostgresURL which searches for the the credential in google's default environment variable file locations, see:

https://github.com/google/go-cloud/blob/e6b94a04072fec4c7106c8301a56436b6fa4135d/postgres/gcppostgres/gcppostgres.go#L66

I would instead benefit from the option of suggesting the JSON directly to a function or having an environment variable which could contain the pure JSON (not a location on disk where the json is stored).

This is useful for any event where one is unable to generate a file on a machine but can dictate the environment variables on them (e.g i would be able to read the credentials i want from a (secret) json environmental variable).

My 1st suggestion here would be to introduce a different environmental variable (e.g GOOGLE_APPLICATION_CREDENTIALS_JSON) that takes precedence over the file environmental variable (GOOGLE_APPLICATION_CREDENTIALS) searched by google.FindDefaultCredentials function here:

https://github.com/google/go-cloud/blob/e6b94a04072fec4c7106c8301a56436b6fa4135d/gcp/gcp.go#L80

and instead call google.CredentialsFromJSON on GOOGLE_APPLICATION_CREDENTIALS_JSON before proceeding to call

google.FindDefaultCredentials: https://github.com/google/go-cloud/blob/e6b94a04072fec4c7106c8301a56436b6fa4135d/gcp/gcp.go#L80

I could draft a PR to introduce the proposed behaviour if it is reasonable

suleimi avatar Mar 30 '22 21:03 suleimi

Suggestion:

// DefaultCredentials obtains the default GCP credentials with Cloud Platform
// scope.
func DefaultCredentials(ctx context.Context) (*google.Credentials, error) {
	// First, try the GOOGLE_APPLICATION_CREDENTIALS_JSON environment variable.
	var adc *google.Credentials
	const envVar = "GOOGLE_APPLICATION_CREDENTIALS_JSON"
	if jsonCredentials := os.Getenv(envVar); jsonCredentials != "" {
		bytes, err := json.Marshal(jsonCredentials)
		if err != nil {
			return nil, fmt.Errorf("google: error getting credentials using %v environment variable: %v", envVar, err)
		}
		adc, err = google.CredentialsFromJSON(ctx, bytes, "https://www.googleapis.com/auth/cloud-platform")
		if err != nil {
			return nil, err
		}
		return adc, nil
	}
	adc, err := google.FindDefaultCredentials(ctx, "https://www.googleapis.com/auth/cloud-platform")
	if err != nil {
		return nil, err
	}
	return adc, nil
}

suleimi avatar Mar 30 '22 21:03 suleimi

Can you create your own URLOpener?

https://github.com/google/go-cloud/blob/e6b94a04072fec4c7106c8301a56436b6fa4135d/postgres/gcppostgres/gcppostgres.go#L89

Or write the JSON to a temp file and use GOOGLE_APPLICATION_CREDENTIALS?

I would prefer not to add custom auth mechanisms to this library if possible.

vangent avatar Mar 30 '22 22:03 vangent

Unfortunately for my usecase i can not write the JSON into a temp file but i do understand the need to not customize the auth mechanism. I'll look into setting up my own URLOpener

suleimi avatar Mar 30 '22 23:03 suleimi

Let's leave the feature request open to see if other people have the same request. If it's a relatively common use case I don't mind your suggestion, but if it's just you I think it makes more sense to have you create your own URLOpener.

vangent avatar Mar 31 '22 00:03 vangent