From 8d6d45b6cde73b704061a2914b49bae1a1d5366e Mon Sep 17 00:00:00 2001 From: Chris Smith Date: Thu, 28 Sep 2023 12:46:05 -0600 Subject: [PATCH] google: add Credentials.UniverseDomain to support TPC Read and expose universe_domain from service account JSON files in CredentialsFromJSONWithParams to support TPC in 1p clients. Change-Id: I3518a0ec8be5ff7235b946cffd88b26ac8d303cf Reviewed-on: https://go-review.googlesource.com/c/oauth2/+/531715 Run-TryBot: Cody Oss TryBot-Result: Gopher Robot Reviewed-by: Cody Oss --- google/default.go | 25 ++++++++++++++++++++---- google/default_test.go | 43 ++++++++++++++++++++++++++++++++++++++++++ google/google.go | 19 ++++++++++--------- 3 files changed, 74 insertions(+), 13 deletions(-) create mode 100644 google/default_test.go diff --git a/google/default.go b/google/default.go index 2cf71f0..1d69bf7 100644 --- a/google/default.go +++ b/google/default.go @@ -19,7 +19,10 @@ import ( "golang.org/x/oauth2/authhandler" ) -const adcSetupURL = "https://cloud.google.com/docs/authentication/external/set-up-adc" +const ( + adcSetupURL = "https://cloud.google.com/docs/authentication/external/set-up-adc" + universeDomainDefault = "googleapis.com" +) // Credentials holds Google credentials, including "Application Default Credentials". // For more details, see: @@ -37,6 +40,18 @@ type Credentials struct { // environment and not with a credentials file, e.g. when code is // running on Google Cloud Platform. JSON []byte + + // universeDomain is the default service domain for a given Cloud universe. + universeDomain string +} + +// UniverseDomain returns the default service domain for a given Cloud universe. +// The default value is "googleapis.com". +func (c *Credentials) UniverseDomain() string { + if c.universeDomain == "" { + return universeDomainDefault + } + return c.universeDomain } // DefaultCredentials is the old name of Credentials. @@ -200,15 +215,17 @@ func CredentialsFromJSONWithParams(ctx context.Context, jsonData []byte, params if err := json.Unmarshal(jsonData, &f); err != nil { return nil, err } + ts, err := f.tokenSource(ctx, params) if err != nil { return nil, err } ts = newErrWrappingTokenSource(ts) return &Credentials{ - ProjectID: f.ProjectID, - TokenSource: ts, - JSON: jsonData, + ProjectID: f.ProjectID, + TokenSource: ts, + JSON: jsonData, + universeDomain: f.UniverseDomain, }, nil } diff --git a/google/default_test.go b/google/default_test.go new file mode 100644 index 0000000..5425e35 --- /dev/null +++ b/google/default_test.go @@ -0,0 +1,43 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package google + +import ( + "context" + "testing" +) + +var jwtJSONKeyUniverseDomain = []byte(`{ + "type": "service_account", + "project_id": "fake_project", + "universe_domain": "example.com", + "private_key_id": "268f54e43a1af97cfc71731688434f45aca15c8b", + "private_key": "super secret key", + "client_email": "gopher@developer.gserviceaccount.com", + "client_id": "gopher.apps.googleusercontent.com", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/gopher%40fake_project.iam.gserviceaccount.com" +}`) + +func TestCredentialsFromJSONWithParams_UniverseDomain(t *testing.T) { + ctx := context.Background() + scope := "https://www.googleapis.com/auth/cloud-platform" + params := CredentialsParams{ + Scopes: []string{scope}, + } + creds, err := CredentialsFromJSONWithParams(ctx, jwtJSONKeyUniverseDomain, params) + if err != nil { + t.Fatal(err) + } + + if want := "fake_project"; creds.ProjectID != want { + t.Fatalf("got %q, want %q", creds.ProjectID, want) + } + if want := "example.com"; creds.UniverseDomain() != want { + t.Fatalf("got %q, want %q", creds.UniverseDomain(), want) + } +} diff --git a/google/google.go b/google/google.go index 8bc6018..c66c535 100644 --- a/google/google.go +++ b/google/google.go @@ -22,10 +22,10 @@ import ( // Endpoint is Google's OAuth 2.0 default endpoint. var Endpoint = oauth2.Endpoint{ - AuthURL: "https://accounts.google.com/o/oauth2/auth", - TokenURL: "https://oauth2.googleapis.com/token", + AuthURL: "https://accounts.google.com/o/oauth2/auth", + TokenURL: "https://oauth2.googleapis.com/token", DeviceAuthURL: "https://oauth2.googleapis.com/device/code", - AuthStyle: oauth2.AuthStyleInParams, + AuthStyle: oauth2.AuthStyleInParams, } // MTLSTokenURL is Google's OAuth 2.0 default mTLS endpoint. @@ -109,12 +109,13 @@ type credentialsFile struct { Type string `json:"type"` // Service Account fields - ClientEmail string `json:"client_email"` - PrivateKeyID string `json:"private_key_id"` - PrivateKey string `json:"private_key"` - AuthURL string `json:"auth_uri"` - TokenURL string `json:"token_uri"` - ProjectID string `json:"project_id"` + ClientEmail string `json:"client_email"` + PrivateKeyID string `json:"private_key_id"` + PrivateKey string `json:"private_key"` + AuthURL string `json:"auth_uri"` + TokenURL string `json:"token_uri"` + ProjectID string `json:"project_id"` + UniverseDomain string `json:"universe_domain"` // User Credential fields // (These typically come from gcloud auth.)