From 1dc7dacd54b4b93f5465b71f2ee8c27e59630454 Mon Sep 17 00:00:00 2001 From: Cody Oss <6331106+codyoss@users.noreply.github.com> Date: Fri, 29 Jan 2021 08:54:02 -0700 Subject: [PATCH] fix(internal): don't use self-signed JWT with impersonation (#788) The limited audience of the base credential will could cause failures as it would not be able to comunicate with the iam credentials api if just default scopes were passed. --- internal/creds.go | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/internal/creds.go b/internal/creds.go index c93daa98c32..87b2f474d00 100644 --- a/internal/creds.go +++ b/internal/creds.go @@ -64,28 +64,38 @@ const ( // credentialsFromJSON returns a google.Credentials based on the input. // -// - If the JSON is a service account and no scopes provided, returns self-signed JWT auth flow -// - Otherwise, returns OAuth 2.0 flow. +// - A self-signed JWT auth flow will be executed if: the data file is a service +// account, no user are scopes provided, an audience is provided, and +// credentials will not be impersonated. +// +// - Otherwise, executes a stanard OAuth 2.0 flow. func credentialsFromJSON(ctx context.Context, data []byte, ds *DialSettings) (*google.Credentials, error) { cred, err := google.CredentialsFromJSON(ctx, data, ds.GetScopes()...) if err != nil { return nil, err } - if len(data) > 0 && len(ds.Scopes) == 0 && (ds.DefaultAudience != "" || len(ds.Audiences) > 0) { - var f struct { - Type string `json:"type"` - // The rest JSON fields are omitted because they are not used. - } - if err := json.Unmarshal(cred.JSON, &f); err != nil { + // Standard OAuth 2.0 Flow + if len(data) == 0 || + len(ds.Scopes) > 0 || + (ds.DefaultAudience == "" && len(ds.Audiences) == 0) || + ds.ImpersonationConfig != nil { + return cred, nil + } + + // Check if JSON is a service account and if so create a self-signed JWT. + var f struct { + Type string `json:"type"` + // The rest JSON fields are omitted because they are not used. + } + if err := json.Unmarshal(cred.JSON, &f); err != nil { + return nil, err + } + if f.Type == serviceAccountKey { + ts, err := selfSignedJWTTokenSource(data, ds.DefaultAudience, ds.Audiences) + if err != nil { return nil, err } - if f.Type == serviceAccountKey { - ts, err := selfSignedJWTTokenSource(data, ds.DefaultAudience, ds.Audiences) - if err != nil { - return nil, err - } - cred.TokenSource = ts - } + cred.TokenSource = ts } return cred, err }