From cb87a576ab4e831574c7b8fbec59c22ea5e650af Mon Sep 17 00:00:00 2001 From: guillaume blaquiere Date: Mon, 23 Aug 2021 10:43:18 +0200 Subject: [PATCH] feat: add service account impersonation support The impersonated_service_account type in the JSON configuration file is taken into account. source_credentials field in the JSON is now supported. Fixes #515 --- google/google.go | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/google/google.go b/google/google.go index 41ced10..c8d1237 100644 --- a/google/google.go +++ b/google/google.go @@ -92,9 +92,10 @@ func JWTConfigFromJSON(jsonKey []byte, scope ...string) (*jwt.Config, error) { // JSON key file types. const ( - serviceAccountKey = "service_account" - userCredentialsKey = "authorized_user" - externalAccountKey = "external_account" + serviceAccountKey = "service_account" + userCredentialsKey = "authorized_user" + externalAccountKey = "external_account" + impersonatedServiceAccount = "impersonated_service_account" ) // credentialsFile is the unmarshalled representation of a credentials file. @@ -124,6 +125,9 @@ type credentialsFile struct { CredentialSource externalaccount.CredentialSource `json:"credential_source"` QuotaProjectID string `json:"quota_project_id"` WorkforcePoolUserProject string `json:"workforce_pool_user_project"` + + // Service account impersonation + SourceCredentials *credentialsFile `json:"source_credentials"` } func (f *credentialsFile) jwtConfig(scopes []string, subject string) *jwt.Config { @@ -180,6 +184,23 @@ func (f *credentialsFile) tokenSource(ctx context.Context, params CredentialsPar WorkforcePoolUserProject: f.WorkforcePoolUserProject, } return cfg.TokenSource(ctx) + case impersonatedServiceAccount: + if f.SourceCredentials == nil { + return nil, errors.New("missing 'source_credentials' field in credentials") + } + + sourceToken, err := f.SourceCredentials.tokenSource(ctx, params) + if err != nil { + return nil, err + } + imp := externalaccount.ImpersonateTokenSource{ + Ctx: ctx, + Url: f.ServiceAccountImpersonationURL, + Scopes: params.Scopes, + Ts: oauth2.ReuseTokenSource(nil, sourceToken), + // Delegates?? -> I don't know how to manage and how to use them here + } + return oauth2.ReuseTokenSource(nil, imp), nil case "": return nil, errors.New("missing 'type' field in credentials") default: