浏览代码

vendor: golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c

Remove the replace rule, and use the version as specified by (indirect) dependencies:

full diff: https://github.com/golang/oauth2/compare/bf48bf16ab8d...f6687ab2804c

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Sebastiaan van Stijn 3 年之前
父节点
当前提交
3ddf696a2d

+ 0 - 1
vendor.mod

@@ -166,7 +166,6 @@ replace (
 	github.com/prometheus/procfs => github.com/prometheus/procfs v0.0.11
 	github.com/vishvananda/netlink => github.com/vishvananda/netlink v1.1.0
 	go.opencensus.io => go.opencensus.io v0.22.3
-	golang.org/x/oauth2 => golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
 	google.golang.org/api => google.golang.org/api v0.8.0
 	google.golang.org/genproto => google.golang.org/genproto v0.0.0-20200227132054-3f1135a288c9
 	google.golang.org/grpc => google.golang.org/grpc v1.27.1

+ 6 - 1
vendor.sum

@@ -795,6 +795,7 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/
 golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
@@ -802,8 +803,11 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c h1:pkQiBZBvdos9qq4wBAHqlzuZHEXo07pqV06ef90u1WI=
+golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -931,6 +935,7 @@ google.golang.org/api v0.8.0 h1:VGGbLNyPF7dvYHhcUGYBBGCRDDK0RRJAI6KCvo0CL+E=
 google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
 google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
 google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
 google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk=

+ 5 - 5
vendor/golang.org/x/oauth2/README.md

@@ -1,7 +1,7 @@
 # OAuth2 for Go
 
+[![Go Reference](https://pkg.go.dev/badge/golang.org/x/oauth2.svg)](https://pkg.go.dev/golang.org/x/oauth2)
 [![Build Status](https://travis-ci.org/golang/oauth2.svg?branch=master)](https://travis-ci.org/golang/oauth2)
-[![GoDoc](https://godoc.org/golang.org/x/oauth2?status.svg)](https://godoc.org/golang.org/x/oauth2)
 
 oauth2 package contains a client implementation for OAuth 2.0 spec.
 
@@ -14,17 +14,17 @@ go get golang.org/x/oauth2
 Or you can manually git clone the repository to
 `$(go env GOPATH)/src/golang.org/x/oauth2`.
 
-See godoc for further documentation and examples.
+See pkg.go.dev for further documentation and examples.
 
-* [godoc.org/golang.org/x/oauth2](https://godoc.org/golang.org/x/oauth2)
-* [godoc.org/golang.org/x/oauth2/google](https://godoc.org/golang.org/x/oauth2/google)
+* [pkg.go.dev/golang.org/x/oauth2](https://pkg.go.dev/golang.org/x/oauth2)
+* [pkg.go.dev/golang.org/x/oauth2/google](https://pkg.go.dev/golang.org/x/oauth2/google)
 
 ## Policy for new packages
 
 We no longer accept new provider-specific packages in this repo if all
 they do is add a single endpoint variable. If you just want to add a
 single endpoint, add it to the
-[godoc.org/golang.org/x/oauth2/endpoints](https://godoc.org/golang.org/x/oauth2/endpoints)
+[pkg.go.dev/golang.org/x/oauth2/endpoints](https://pkg.go.dev/golang.org/x/oauth2/endpoints)
 package.
 
 ## Report Issues / Send Patches

+ 56 - 0
vendor/golang.org/x/oauth2/authhandler/authhandler.go

@@ -0,0 +1,56 @@
+// Copyright 2021 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 authhandler implements a TokenSource to support
+// "three-legged OAuth 2.0" via a custom AuthorizationHandler.
+package authhandler
+
+import (
+	"context"
+	"errors"
+
+	"golang.org/x/oauth2"
+)
+
+// AuthorizationHandler is a 3-legged-OAuth helper that prompts
+// the user for OAuth consent at the specified auth code URL
+// and returns an auth code and state upon approval.
+type AuthorizationHandler func(authCodeURL string) (code string, state string, err error)
+
+// TokenSource returns an oauth2.TokenSource that fetches access tokens
+// using 3-legged-OAuth flow.
+//
+// The provided context.Context is used for oauth2 Exchange operation.
+//
+// The provided oauth2.Config should be a full configuration containing AuthURL,
+// TokenURL, and Scope.
+//
+// An environment-specific AuthorizationHandler is used to obtain user consent.
+//
+// Per the OAuth protocol, a unique "state" string should be specified here.
+// This token source will verify that the "state" is identical in the request
+// and response before exchanging the auth code for OAuth token to prevent CSRF
+// attacks.
+func TokenSource(ctx context.Context, config *oauth2.Config, state string, authHandler AuthorizationHandler) oauth2.TokenSource {
+	return oauth2.ReuseTokenSource(nil, authHandlerSource{config: config, ctx: ctx, authHandler: authHandler, state: state})
+}
+
+type authHandlerSource struct {
+	ctx         context.Context
+	config      *oauth2.Config
+	authHandler AuthorizationHandler
+	state       string
+}
+
+func (source authHandlerSource) Token() (*oauth2.Token, error) {
+	url := source.config.AuthCodeURL(source.state)
+	code, state, err := source.authHandler(url)
+	if err != nil {
+		return nil, err
+	}
+	if state != source.state {
+		return nil, errors.New("state mismatch in 3-legged-OAuth flow")
+	}
+	return source.config.Exchange(source.ctx, code)
+}

+ 1 - 0
vendor/golang.org/x/oauth2/google/appengine_gen1.go

@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build appengine
 // +build appengine
 
 // This file applies to App Engine first generation runtimes (<= Go 1.9).

+ 1 - 0
vendor/golang.org/x/oauth2/google/appengine_gen2_flex.go

@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build !appengine
 // +build !appengine
 
 // This file applies to App Engine second generation runtimes (>= Go 1.11) and App Engine flexible.

+ 81 - 14
vendor/golang.org/x/oauth2/google/default.go

@@ -16,11 +16,16 @@ import (
 
 	"cloud.google.com/go/compute/metadata"
 	"golang.org/x/oauth2"
+	"golang.org/x/oauth2/authhandler"
 )
 
 // Credentials holds Google credentials, including "Application Default Credentials".
 // For more details, see:
 // https://developers.google.com/accounts/docs/application-default-credentials
+// Credentials from external accounts (workload identity federation) are used to
+// identify a particular application from an on-prem or non-Google Cloud platform
+// including Amazon Web Services (AWS), Microsoft Azure or any identity provider
+// that supports OpenID Connect (OIDC).
 type Credentials struct {
 	ProjectID   string // may be empty
 	TokenSource oauth2.TokenSource
@@ -37,6 +42,32 @@ type Credentials struct {
 // Deprecated: use Credentials instead.
 type DefaultCredentials = Credentials
 
+// CredentialsParams holds user supplied parameters that are used together
+// with a credentials file for building a Credentials object.
+type CredentialsParams struct {
+	// Scopes is the list OAuth scopes. Required.
+	// Example: https://www.googleapis.com/auth/cloud-platform
+	Scopes []string
+
+	// Subject is the user email used for domain wide delegation (see
+	// https://developers.google.com/identity/protocols/oauth2/service-account#delegatingauthority).
+	// Optional.
+	Subject string
+
+	// AuthHandler is the AuthorizationHandler used for 3-legged OAuth flow. Optional.
+	AuthHandler authhandler.AuthorizationHandler
+
+	// State is a unique string used with AuthHandler. Optional.
+	State string
+}
+
+func (params CredentialsParams) deepCopy() CredentialsParams {
+	paramsCopy := params
+	paramsCopy.Scopes = make([]string, len(params.Scopes))
+	copy(paramsCopy.Scopes, params.Scopes)
+	return paramsCopy
+}
+
 // DefaultClient returns an HTTP Client that uses the
 // DefaultTokenSource to obtain authentication credentials.
 func DefaultClient(ctx context.Context, scope ...string) (*http.Client, error) {
@@ -58,13 +89,17 @@ func DefaultTokenSource(ctx context.Context, scope ...string) (oauth2.TokenSourc
 	return creds.TokenSource, nil
 }
 
-// FindDefaultCredentials searches for "Application Default Credentials".
+// FindDefaultCredentialsWithParams searches for "Application Default Credentials".
 //
 // It looks for credentials in the following places,
 // preferring the first location found:
 //
 //   1. A JSON file whose path is specified by the
 //      GOOGLE_APPLICATION_CREDENTIALS environment variable.
+//      For workload identity federation, refer to
+//      https://cloud.google.com/iam/docs/how-to#using-workload-identity-federation on
+//      how to generate the JSON configuration file for on-prem/non-Google cloud
+//      platforms.
 //   2. A JSON file in a location known to the gcloud command-line tool.
 //      On Windows, this is %APPDATA%/gcloud/application_default_credentials.json.
 //      On other systems, $HOME/.config/gcloud/application_default_credentials.json.
@@ -73,11 +108,14 @@ func DefaultTokenSource(ctx context.Context, scope ...string) (oauth2.TokenSourc
 //   4. On Google Compute Engine, Google App Engine standard second generation runtimes
 //      (>= Go 1.11), and Google App Engine flexible environment, it fetches
 //      credentials from the metadata server.
-func FindDefaultCredentials(ctx context.Context, scopes ...string) (*Credentials, error) {
+func FindDefaultCredentialsWithParams(ctx context.Context, params CredentialsParams) (*Credentials, error) {
+	// Make defensive copy of the slices in params.
+	params = params.deepCopy()
+
 	// First, try the environment variable.
 	const envVar = "GOOGLE_APPLICATION_CREDENTIALS"
 	if filename := os.Getenv(envVar); filename != "" {
-		creds, err := readCredentialsFile(ctx, filename, scopes)
+		creds, err := readCredentialsFile(ctx, filename, params)
 		if err != nil {
 			return nil, fmt.Errorf("google: error getting credentials using %v environment variable: %v", envVar, err)
 		}
@@ -86,7 +124,7 @@ func FindDefaultCredentials(ctx context.Context, scopes ...string) (*Credentials
 
 	// Second, try a well-known file.
 	filename := wellKnownFile()
-	if creds, err := readCredentialsFile(ctx, filename, scopes); err == nil {
+	if creds, err := readCredentialsFile(ctx, filename, params); err == nil {
 		return creds, nil
 	} else if !os.IsNotExist(err) {
 		return nil, fmt.Errorf("google: error getting credentials using well-known file (%v): %v", filename, err)
@@ -98,7 +136,7 @@ func FindDefaultCredentials(ctx context.Context, scopes ...string) (*Credentials
 	if appengineTokenFunc != nil {
 		return &DefaultCredentials{
 			ProjectID:   appengineAppIDFunc(ctx),
-			TokenSource: AppEngineTokenSource(ctx, scopes...),
+			TokenSource: AppEngineTokenSource(ctx, params.Scopes...),
 		}, nil
 	}
 
@@ -108,7 +146,7 @@ func FindDefaultCredentials(ctx context.Context, scopes ...string) (*Credentials
 		id, _ := metadata.ProjectID()
 		return &DefaultCredentials{
 			ProjectID:   id,
-			TokenSource: ComputeTokenSource("", scopes...),
+			TokenSource: ComputeTokenSource("", params.Scopes...),
 		}, nil
 	}
 
@@ -117,16 +155,38 @@ func FindDefaultCredentials(ctx context.Context, scopes ...string) (*Credentials
 	return nil, fmt.Errorf("google: could not find default credentials. See %v for more information.", url)
 }
 
-// CredentialsFromJSON obtains Google credentials from a JSON value. The JSON can
-// represent either a Google Developers Console client_credentials.json file (as in
-// ConfigFromJSON) or a Google Developers service account key file (as in
-// JWTConfigFromJSON).
-func CredentialsFromJSON(ctx context.Context, jsonData []byte, scopes ...string) (*Credentials, error) {
+// FindDefaultCredentials invokes FindDefaultCredentialsWithParams with the specified scopes.
+func FindDefaultCredentials(ctx context.Context, scopes ...string) (*Credentials, error) {
+	var params CredentialsParams
+	params.Scopes = scopes
+	return FindDefaultCredentialsWithParams(ctx, params)
+}
+
+// CredentialsFromJSONWithParams obtains Google credentials from a JSON value. The JSON can
+// represent either a Google Developers Console client_credentials.json file (as in ConfigFromJSON),
+// a Google Developers service account key file, a gcloud user credentials file (a.k.a. refresh
+// token JSON), or the JSON configuration file for workload identity federation in non-Google cloud
+// platforms (see https://cloud.google.com/iam/docs/how-to#using-workload-identity-federation).
+func CredentialsFromJSONWithParams(ctx context.Context, jsonData []byte, params CredentialsParams) (*Credentials, error) {
+	// Make defensive copy of the slices in params.
+	params = params.deepCopy()
+
+	// First, attempt to parse jsonData as a Google Developers Console client_credentials.json.
+	config, _ := ConfigFromJSON(jsonData, params.Scopes...)
+	if config != nil {
+		return &Credentials{
+			ProjectID:   "",
+			TokenSource: authhandler.TokenSource(ctx, config, params.State, params.AuthHandler),
+			JSON:        jsonData,
+		}, nil
+	}
+
+	// Otherwise, parse jsonData as one of the other supported credentials files.
 	var f credentialsFile
 	if err := json.Unmarshal(jsonData, &f); err != nil {
 		return nil, err
 	}
-	ts, err := f.tokenSource(ctx, append([]string(nil), scopes...))
+	ts, err := f.tokenSource(ctx, params)
 	if err != nil {
 		return nil, err
 	}
@@ -137,6 +197,13 @@ func CredentialsFromJSON(ctx context.Context, jsonData []byte, scopes ...string)
 	}, nil
 }
 
+// CredentialsFromJSON invokes CredentialsFromJSONWithParams with the specified scopes.
+func CredentialsFromJSON(ctx context.Context, jsonData []byte, scopes ...string) (*Credentials, error) {
+	var params CredentialsParams
+	params.Scopes = scopes
+	return CredentialsFromJSONWithParams(ctx, jsonData, params)
+}
+
 func wellKnownFile() string {
 	const f = "application_default_credentials.json"
 	if runtime.GOOS == "windows" {
@@ -145,10 +212,10 @@ func wellKnownFile() string {
 	return filepath.Join(guessUnixHomeDir(), ".config", "gcloud", f)
 }
 
-func readCredentialsFile(ctx context.Context, filename string, scopes []string) (*DefaultCredentials, error) {
+func readCredentialsFile(ctx context.Context, filename string, params CredentialsParams) (*DefaultCredentials, error) {
 	b, err := ioutil.ReadFile(filename)
 	if err != nil {
 		return nil, err
 	}
-	return CredentialsFromJSON(ctx, b, scopes...)
+	return CredentialsFromJSONWithParams(ctx, b, params)
 }

+ 41 - 2
vendor/golang.org/x/oauth2/google/doc.go

@@ -4,13 +4,16 @@
 
 // Package google provides support for making OAuth2 authorized and authenticated
 // HTTP requests to Google APIs. It supports the Web server flow, client-side
-// credentials, service accounts, Google Compute Engine service accounts, and Google
-// App Engine service accounts.
+// credentials, service accounts, Google Compute Engine service accounts, Google
+// App Engine service accounts and workload identity federation from non-Google
+// cloud platforms.
 //
 // A brief overview of the package follows. For more information, please read
 // https://developers.google.com/accounts/docs/OAuth2
 // and
 // https://developers.google.com/accounts/docs/application-default-credentials.
+// For more information on using workload identity federation, refer to
+// https://cloud.google.com/iam/docs/how-to#using-workload-identity-federation.
 //
 // OAuth2 Configs
 //
@@ -19,6 +22,35 @@
 // the other by JWTConfigFromJSON. The returned Config can be used to obtain a TokenSource or
 // create an http.Client.
 //
+// Workload Identity Federation
+//
+// Using workload identity federation, your application can access Google Cloud
+// resources from Amazon Web Services (AWS), Microsoft Azure or any identity
+// provider that supports OpenID Connect (OIDC).
+// Traditionally, applications running outside Google Cloud have used service
+// account keys to access Google Cloud resources. Using identity federation,
+// you can allow your workload to impersonate a service account.
+// This lets you access Google Cloud resources directly, eliminating the
+// maintenance and security burden associated with service account keys.
+//
+// Follow the detailed instructions on how to configure Workload Identity Federation
+// in various platforms:
+//
+//   Amazon Web Services (AWS): https://cloud.google.com/iam/docs/access-resources-aws
+//   Microsoft Azure: https://cloud.google.com/iam/docs/access-resources-azure
+//   OIDC identity provider: https://cloud.google.com/iam/docs/access-resources-oidc
+//
+// For OIDC providers, the library can retrieve OIDC tokens either from a
+// local file location (file-sourced credentials) or from a local server
+// (URL-sourced credentials).
+// For file-sourced credentials, a background process needs to be continuously
+// refreshing the file location with a new OIDC token prior to expiration.
+// For tokens with one hour lifetimes, the token needs to be updated in the file
+// every hour. The token can be stored directly as plain text or in JSON format.
+// For URL-sourced credentials, a local server needs to host a GET endpoint to
+// return the OIDC token. The response can be in plain text or JSON.
+// Additional required request headers can also be specified.
+//
 //
 // Credentials
 //
@@ -29,6 +61,13 @@
 // FindDefaultCredentials looks in some well-known places for a credentials file, and
 // will call AppEngineTokenSource or ComputeTokenSource as needed.
 //
+// Application Default Credentials also support workload identity federation to
+// access Google Cloud resources from non-Google Cloud platforms including Amazon
+// Web Services (AWS), Microsoft Azure or any identity provider that supports
+// OpenID Connect (OIDC). Workload identity federation is recommended for
+// non-Google Cloud environments as it avoids the need to download, manage and
+// store service account private keys locally.
+//
 // DefaultClient and DefaultTokenSource are convenience methods. They first call FindDefaultCredentials,
 // then use the credentials to construct an http.Client or an oauth2.TokenSource.
 //

+ 45 - 8
vendor/golang.org/x/oauth2/google/google.go

@@ -15,10 +15,11 @@ import (
 
 	"cloud.google.com/go/compute/metadata"
 	"golang.org/x/oauth2"
+	"golang.org/x/oauth2/google/internal/externalaccount"
 	"golang.org/x/oauth2/jwt"
 )
 
-// Endpoint is Google's OAuth 2.0 endpoint.
+// 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",
@@ -86,23 +87,25 @@ func JWTConfigFromJSON(jsonKey []byte, scope ...string) (*jwt.Config, error) {
 		return nil, fmt.Errorf("google: read JWT from JSON credentials: 'type' field is %q (expected %q)", f.Type, serviceAccountKey)
 	}
 	scope = append([]string(nil), scope...) // copy
-	return f.jwtConfig(scope), nil
+	return f.jwtConfig(scope, ""), nil
 }
 
 // JSON key file types.
 const (
 	serviceAccountKey  = "service_account"
 	userCredentialsKey = "authorized_user"
+	externalAccountKey = "external_account"
 )
 
 // credentialsFile is the unmarshalled representation of a credentials file.
 type credentialsFile struct {
-	Type string `json:"type"` // serviceAccountKey or userCredentialsKey
+	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"`
 
@@ -111,15 +114,25 @@ type credentialsFile struct {
 	ClientSecret string `json:"client_secret"`
 	ClientID     string `json:"client_id"`
 	RefreshToken string `json:"refresh_token"`
+
+	// External Account fields
+	Audience                       string                           `json:"audience"`
+	SubjectTokenType               string                           `json:"subject_token_type"`
+	TokenURLExternal               string                           `json:"token_url"`
+	TokenInfoURL                   string                           `json:"token_info_url"`
+	ServiceAccountImpersonationURL string                           `json:"service_account_impersonation_url"`
+	CredentialSource               externalaccount.CredentialSource `json:"credential_source"`
+	QuotaProjectID                 string                           `json:"quota_project_id"`
 }
 
-func (f *credentialsFile) jwtConfig(scopes []string) *jwt.Config {
+func (f *credentialsFile) jwtConfig(scopes []string, subject string) *jwt.Config {
 	cfg := &jwt.Config{
 		Email:        f.ClientEmail,
 		PrivateKey:   []byte(f.PrivateKey),
 		PrivateKeyID: f.PrivateKeyID,
 		Scopes:       scopes,
 		TokenURL:     f.TokenURL,
+		Subject:      subject, // This is the user email to impersonate
 	}
 	if cfg.TokenURL == "" {
 		cfg.TokenURL = JWTTokenURL
@@ -127,20 +140,44 @@ func (f *credentialsFile) jwtConfig(scopes []string) *jwt.Config {
 	return cfg
 }
 
-func (f *credentialsFile) tokenSource(ctx context.Context, scopes []string) (oauth2.TokenSource, error) {
+func (f *credentialsFile) tokenSource(ctx context.Context, params CredentialsParams) (oauth2.TokenSource, error) {
 	switch f.Type {
 	case serviceAccountKey:
-		cfg := f.jwtConfig(scopes)
+		cfg := f.jwtConfig(params.Scopes, params.Subject)
 		return cfg.TokenSource(ctx), nil
 	case userCredentialsKey:
 		cfg := &oauth2.Config{
 			ClientID:     f.ClientID,
 			ClientSecret: f.ClientSecret,
-			Scopes:       scopes,
-			Endpoint:     Endpoint,
+			Scopes:       params.Scopes,
+			Endpoint: oauth2.Endpoint{
+				AuthURL:   f.AuthURL,
+				TokenURL:  f.TokenURL,
+				AuthStyle: oauth2.AuthStyleInParams,
+			},
+		}
+		if cfg.Endpoint.AuthURL == "" {
+			cfg.Endpoint.AuthURL = Endpoint.AuthURL
+		}
+		if cfg.Endpoint.TokenURL == "" {
+			cfg.Endpoint.TokenURL = Endpoint.TokenURL
 		}
 		tok := &oauth2.Token{RefreshToken: f.RefreshToken}
 		return cfg.TokenSource(ctx, tok), nil
+	case externalAccountKey:
+		cfg := &externalaccount.Config{
+			Audience:                       f.Audience,
+			SubjectTokenType:               f.SubjectTokenType,
+			TokenURL:                       f.TokenURLExternal,
+			TokenInfoURL:                   f.TokenInfoURL,
+			ServiceAccountImpersonationURL: f.ServiceAccountImpersonationURL,
+			ClientSecret:                   f.ClientSecret,
+			ClientID:                       f.ClientID,
+			CredentialSource:               f.CredentialSource,
+			QuotaProjectID:                 f.QuotaProjectID,
+			Scopes:                         params.Scopes,
+		}
+		return cfg.TokenSource(ctx), nil
 	case "":
 		return nil, errors.New("missing 'type' field in credentials")
 	default:

+ 466 - 0
vendor/golang.org/x/oauth2/google/internal/externalaccount/aws.go

@@ -0,0 +1,466 @@
+// Copyright 2021 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 externalaccount
+
+import (
+	"bytes"
+	"context"
+	"crypto/hmac"
+	"crypto/sha256"
+	"encoding/hex"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"golang.org/x/oauth2"
+	"io"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"os"
+	"path"
+	"sort"
+	"strings"
+	"time"
+)
+
+type awsSecurityCredentials struct {
+	AccessKeyID     string `json:"AccessKeyID"`
+	SecretAccessKey string `json:"SecretAccessKey"`
+	SecurityToken   string `json:"Token"`
+}
+
+// awsRequestSigner is a utility class to sign http requests using a AWS V4 signature.
+type awsRequestSigner struct {
+	RegionName             string
+	AwsSecurityCredentials awsSecurityCredentials
+}
+
+// getenv aliases os.Getenv for testing
+var getenv = os.Getenv
+
+const (
+	// AWS Signature Version 4 signing algorithm identifier.
+	awsAlgorithm = "AWS4-HMAC-SHA256"
+
+	// The termination string for the AWS credential scope value as defined in
+	// https://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html
+	awsRequestType = "aws4_request"
+
+	// The AWS authorization header name for the security session token if available.
+	awsSecurityTokenHeader = "x-amz-security-token"
+
+	// The AWS authorization header name for the auto-generated date.
+	awsDateHeader = "x-amz-date"
+
+	awsTimeFormatLong  = "20060102T150405Z"
+	awsTimeFormatShort = "20060102"
+)
+
+func getSha256(input []byte) (string, error) {
+	hash := sha256.New()
+	if _, err := hash.Write(input); err != nil {
+		return "", err
+	}
+	return hex.EncodeToString(hash.Sum(nil)), nil
+}
+
+func getHmacSha256(key, input []byte) ([]byte, error) {
+	hash := hmac.New(sha256.New, key)
+	if _, err := hash.Write(input); err != nil {
+		return nil, err
+	}
+	return hash.Sum(nil), nil
+}
+
+func cloneRequest(r *http.Request) *http.Request {
+	r2 := new(http.Request)
+	*r2 = *r
+	if r.Header != nil {
+		r2.Header = make(http.Header, len(r.Header))
+
+		// Find total number of values.
+		headerCount := 0
+		for _, headerValues := range r.Header {
+			headerCount += len(headerValues)
+		}
+		copiedHeaders := make([]string, headerCount) // shared backing array for headers' values
+
+		for headerKey, headerValues := range r.Header {
+			headerCount = copy(copiedHeaders, headerValues)
+			r2.Header[headerKey] = copiedHeaders[:headerCount:headerCount]
+			copiedHeaders = copiedHeaders[headerCount:]
+		}
+	}
+	return r2
+}
+
+func canonicalPath(req *http.Request) string {
+	result := req.URL.EscapedPath()
+	if result == "" {
+		return "/"
+	}
+	return path.Clean(result)
+}
+
+func canonicalQuery(req *http.Request) string {
+	queryValues := req.URL.Query()
+	for queryKey := range queryValues {
+		sort.Strings(queryValues[queryKey])
+	}
+	return queryValues.Encode()
+}
+
+func canonicalHeaders(req *http.Request) (string, string) {
+	// Header keys need to be sorted alphabetically.
+	var headers []string
+	lowerCaseHeaders := make(http.Header)
+	for k, v := range req.Header {
+		k := strings.ToLower(k)
+		if _, ok := lowerCaseHeaders[k]; ok {
+			// include additional values
+			lowerCaseHeaders[k] = append(lowerCaseHeaders[k], v...)
+		} else {
+			headers = append(headers, k)
+			lowerCaseHeaders[k] = v
+		}
+	}
+	sort.Strings(headers)
+
+	var fullHeaders bytes.Buffer
+	for _, header := range headers {
+		headerValue := strings.Join(lowerCaseHeaders[header], ",")
+		fullHeaders.WriteString(header)
+		fullHeaders.WriteRune(':')
+		fullHeaders.WriteString(headerValue)
+		fullHeaders.WriteRune('\n')
+	}
+
+	return strings.Join(headers, ";"), fullHeaders.String()
+}
+
+func requestDataHash(req *http.Request) (string, error) {
+	var requestData []byte
+	if req.Body != nil {
+		requestBody, err := req.GetBody()
+		if err != nil {
+			return "", err
+		}
+		defer requestBody.Close()
+
+		requestData, err = ioutil.ReadAll(io.LimitReader(requestBody, 1<<20))
+		if err != nil {
+			return "", err
+		}
+	}
+
+	return getSha256(requestData)
+}
+
+func requestHost(req *http.Request) string {
+	if req.Host != "" {
+		return req.Host
+	}
+	return req.URL.Host
+}
+
+func canonicalRequest(req *http.Request, canonicalHeaderColumns, canonicalHeaderData string) (string, error) {
+	dataHash, err := requestDataHash(req)
+	if err != nil {
+		return "", err
+	}
+
+	return fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n%s", req.Method, canonicalPath(req), canonicalQuery(req), canonicalHeaderData, canonicalHeaderColumns, dataHash), nil
+}
+
+// SignRequest adds the appropriate headers to an http.Request
+// or returns an error if something prevented this.
+func (rs *awsRequestSigner) SignRequest(req *http.Request) error {
+	signedRequest := cloneRequest(req)
+	timestamp := now()
+
+	signedRequest.Header.Add("host", requestHost(req))
+
+	if rs.AwsSecurityCredentials.SecurityToken != "" {
+		signedRequest.Header.Add(awsSecurityTokenHeader, rs.AwsSecurityCredentials.SecurityToken)
+	}
+
+	if signedRequest.Header.Get("date") == "" {
+		signedRequest.Header.Add(awsDateHeader, timestamp.Format(awsTimeFormatLong))
+	}
+
+	authorizationCode, err := rs.generateAuthentication(signedRequest, timestamp)
+	if err != nil {
+		return err
+	}
+	signedRequest.Header.Set("Authorization", authorizationCode)
+
+	req.Header = signedRequest.Header
+	return nil
+}
+
+func (rs *awsRequestSigner) generateAuthentication(req *http.Request, timestamp time.Time) (string, error) {
+	canonicalHeaderColumns, canonicalHeaderData := canonicalHeaders(req)
+
+	dateStamp := timestamp.Format(awsTimeFormatShort)
+	serviceName := ""
+	if splitHost := strings.Split(requestHost(req), "."); len(splitHost) > 0 {
+		serviceName = splitHost[0]
+	}
+
+	credentialScope := fmt.Sprintf("%s/%s/%s/%s", dateStamp, rs.RegionName, serviceName, awsRequestType)
+
+	requestString, err := canonicalRequest(req, canonicalHeaderColumns, canonicalHeaderData)
+	if err != nil {
+		return "", err
+	}
+	requestHash, err := getSha256([]byte(requestString))
+	if err != nil {
+		return "", err
+	}
+
+	stringToSign := fmt.Sprintf("%s\n%s\n%s\n%s", awsAlgorithm, timestamp.Format(awsTimeFormatLong), credentialScope, requestHash)
+
+	signingKey := []byte("AWS4" + rs.AwsSecurityCredentials.SecretAccessKey)
+	for _, signingInput := range []string{
+		dateStamp, rs.RegionName, serviceName, awsRequestType, stringToSign,
+	} {
+		signingKey, err = getHmacSha256(signingKey, []byte(signingInput))
+		if err != nil {
+			return "", err
+		}
+	}
+
+	return fmt.Sprintf("%s Credential=%s/%s, SignedHeaders=%s, Signature=%s", awsAlgorithm, rs.AwsSecurityCredentials.AccessKeyID, credentialScope, canonicalHeaderColumns, hex.EncodeToString(signingKey)), nil
+}
+
+type awsCredentialSource struct {
+	EnvironmentID               string
+	RegionURL                   string
+	RegionalCredVerificationURL string
+	CredVerificationURL         string
+	TargetResource              string
+	requestSigner               *awsRequestSigner
+	region                      string
+	ctx                         context.Context
+	client                      *http.Client
+}
+
+type awsRequestHeader struct {
+	Key   string `json:"key"`
+	Value string `json:"value"`
+}
+
+type awsRequest struct {
+	URL     string             `json:"url"`
+	Method  string             `json:"method"`
+	Headers []awsRequestHeader `json:"headers"`
+}
+
+func (cs awsCredentialSource) doRequest(req *http.Request) (*http.Response, error) {
+	if cs.client == nil {
+		cs.client = oauth2.NewClient(cs.ctx, nil)
+	}
+	return cs.client.Do(req.WithContext(cs.ctx))
+}
+
+func (cs awsCredentialSource) subjectToken() (string, error) {
+	if cs.requestSigner == nil {
+		awsSecurityCredentials, err := cs.getSecurityCredentials()
+		if err != nil {
+			return "", err
+		}
+
+		if cs.region, err = cs.getRegion(); err != nil {
+			return "", err
+		}
+
+		cs.requestSigner = &awsRequestSigner{
+			RegionName:             cs.region,
+			AwsSecurityCredentials: awsSecurityCredentials,
+		}
+	}
+
+	// Generate the signed request to AWS STS GetCallerIdentity API.
+	// Use the required regional endpoint. Otherwise, the request will fail.
+	req, err := http.NewRequest("POST", strings.Replace(cs.RegionalCredVerificationURL, "{region}", cs.region, 1), nil)
+	if err != nil {
+		return "", err
+	}
+	// The full, canonical resource name of the workload identity pool
+	// provider, with or without the HTTPS prefix.
+	// Including this header as part of the signature is recommended to
+	// ensure data integrity.
+	if cs.TargetResource != "" {
+		req.Header.Add("x-goog-cloud-target-resource", cs.TargetResource)
+	}
+	cs.requestSigner.SignRequest(req)
+
+	/*
+	   The GCP STS endpoint expects the headers to be formatted as:
+	   # [
+	   #   {key: 'x-amz-date', value: '...'},
+	   #   {key: 'Authorization', value: '...'},
+	   #   ...
+	   # ]
+	   # And then serialized as:
+	   # quote(json.dumps({
+	   #   url: '...',
+	   #   method: 'POST',
+	   #   headers: [{key: 'x-amz-date', value: '...'}, ...]
+	   # }))
+	*/
+
+	awsSignedReq := awsRequest{
+		URL:    req.URL.String(),
+		Method: "POST",
+	}
+	for headerKey, headerList := range req.Header {
+		for _, headerValue := range headerList {
+			awsSignedReq.Headers = append(awsSignedReq.Headers, awsRequestHeader{
+				Key:   headerKey,
+				Value: headerValue,
+			})
+		}
+	}
+	sort.Slice(awsSignedReq.Headers, func(i, j int) bool {
+		headerCompare := strings.Compare(awsSignedReq.Headers[i].Key, awsSignedReq.Headers[j].Key)
+		if headerCompare == 0 {
+			return strings.Compare(awsSignedReq.Headers[i].Value, awsSignedReq.Headers[j].Value) < 0
+		}
+		return headerCompare < 0
+	})
+
+	result, err := json.Marshal(awsSignedReq)
+	if err != nil {
+		return "", err
+	}
+	return url.QueryEscape(string(result)), nil
+}
+
+func (cs *awsCredentialSource) getRegion() (string, error) {
+	if envAwsRegion := getenv("AWS_REGION"); envAwsRegion != "" {
+		return envAwsRegion, nil
+	}
+
+	if cs.RegionURL == "" {
+		return "", errors.New("oauth2/google: unable to determine AWS region")
+	}
+
+	req, err := http.NewRequest("GET", cs.RegionURL, nil)
+	if err != nil {
+		return "", err
+	}
+
+	resp, err := cs.doRequest(req)
+	if err != nil {
+		return "", err
+	}
+	defer resp.Body.Close()
+
+	respBody, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1<<20))
+	if err != nil {
+		return "", err
+	}
+
+	if resp.StatusCode != 200 {
+		return "", fmt.Errorf("oauth2/google: unable to retrieve AWS region - %s", string(respBody))
+	}
+
+	// This endpoint will return the region in format: us-east-2b.
+	// Only the us-east-2 part should be used.
+	respBodyEnd := 0
+	if len(respBody) > 1 {
+		respBodyEnd = len(respBody) - 1
+	}
+	return string(respBody[:respBodyEnd]), nil
+}
+
+func (cs *awsCredentialSource) getSecurityCredentials() (result awsSecurityCredentials, err error) {
+	if accessKeyID := getenv("AWS_ACCESS_KEY_ID"); accessKeyID != "" {
+		if secretAccessKey := getenv("AWS_SECRET_ACCESS_KEY"); secretAccessKey != "" {
+			return awsSecurityCredentials{
+				AccessKeyID:     accessKeyID,
+				SecretAccessKey: secretAccessKey,
+				SecurityToken:   getenv("AWS_SESSION_TOKEN"),
+			}, nil
+		}
+	}
+
+	roleName, err := cs.getMetadataRoleName()
+	if err != nil {
+		return
+	}
+
+	credentials, err := cs.getMetadataSecurityCredentials(roleName)
+	if err != nil {
+		return
+	}
+
+	if credentials.AccessKeyID == "" {
+		return result, errors.New("oauth2/google: missing AccessKeyId credential")
+	}
+
+	if credentials.SecretAccessKey == "" {
+		return result, errors.New("oauth2/google: missing SecretAccessKey credential")
+	}
+
+	return credentials, nil
+}
+
+func (cs *awsCredentialSource) getMetadataSecurityCredentials(roleName string) (awsSecurityCredentials, error) {
+	var result awsSecurityCredentials
+
+	req, err := http.NewRequest("GET", fmt.Sprintf("%s/%s", cs.CredVerificationURL, roleName), nil)
+	if err != nil {
+		return result, err
+	}
+	req.Header.Add("Content-Type", "application/json")
+
+	resp, err := cs.doRequest(req)
+	if err != nil {
+		return result, err
+	}
+	defer resp.Body.Close()
+
+	respBody, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1<<20))
+	if err != nil {
+		return result, err
+	}
+
+	if resp.StatusCode != 200 {
+		return result, fmt.Errorf("oauth2/google: unable to retrieve AWS security credentials - %s", string(respBody))
+	}
+
+	err = json.Unmarshal(respBody, &result)
+	return result, err
+}
+
+func (cs *awsCredentialSource) getMetadataRoleName() (string, error) {
+	if cs.CredVerificationURL == "" {
+		return "", errors.New("oauth2/google: unable to determine the AWS metadata server security credentials endpoint")
+	}
+
+	req, err := http.NewRequest("GET", cs.CredVerificationURL, nil)
+	if err != nil {
+		return "", err
+	}
+
+	resp, err := cs.doRequest(req)
+	if err != nil {
+		return "", err
+	}
+	defer resp.Body.Close()
+
+	respBody, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1<<20))
+	if err != nil {
+		return "", err
+	}
+
+	if resp.StatusCode != 200 {
+		return "", fmt.Errorf("oauth2/google: unable to retrieve AWS role name - %s", string(respBody))
+	}
+
+	return string(respBody), nil
+}

+ 163 - 0
vendor/golang.org/x/oauth2/google/internal/externalaccount/basecredentials.go

@@ -0,0 +1,163 @@
+// Copyright 2020 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 externalaccount
+
+import (
+	"context"
+	"fmt"
+	"golang.org/x/oauth2"
+	"net/http"
+	"strconv"
+	"time"
+)
+
+// now aliases time.Now for testing
+var now = func() time.Time {
+	return time.Now().UTC()
+}
+
+// Config stores the configuration for fetching tokens with external credentials.
+type Config struct {
+	Audience                       string
+	SubjectTokenType               string
+	TokenURL                       string
+	TokenInfoURL                   string
+	ServiceAccountImpersonationURL string
+	ClientSecret                   string
+	ClientID                       string
+	CredentialSource               CredentialSource
+	QuotaProjectID                 string
+	Scopes                         []string
+}
+
+// TokenSource Returns an external account TokenSource struct. This is to be called by package google to construct a google.Credentials.
+func (c *Config) TokenSource(ctx context.Context) oauth2.TokenSource {
+	ts := tokenSource{
+		ctx:  ctx,
+		conf: c,
+	}
+	if c.ServiceAccountImpersonationURL == "" {
+		return oauth2.ReuseTokenSource(nil, ts)
+	}
+	scopes := c.Scopes
+	ts.conf.Scopes = []string{"https://www.googleapis.com/auth/cloud-platform"}
+	imp := impersonateTokenSource{
+		ctx:    ctx,
+		url:    c.ServiceAccountImpersonationURL,
+		scopes: scopes,
+		ts:     oauth2.ReuseTokenSource(nil, ts),
+	}
+	return oauth2.ReuseTokenSource(nil, imp)
+}
+
+// Subject token file types.
+const (
+	fileTypeText = "text"
+	fileTypeJSON = "json"
+)
+
+type format struct {
+	// Type is either "text" or "json".  When not provided "text" type is assumed.
+	Type string `json:"type"`
+	// SubjectTokenFieldName is only required for JSON format.  This would be "access_token" for azure.
+	SubjectTokenFieldName string `json:"subject_token_field_name"`
+}
+
+// CredentialSource stores the information necessary to retrieve the credentials for the STS exchange.
+type CredentialSource struct {
+	File string `json:"file"`
+
+	URL     string            `json:"url"`
+	Headers map[string]string `json:"headers"`
+
+	EnvironmentID               string `json:"environment_id"`
+	RegionURL                   string `json:"region_url"`
+	RegionalCredVerificationURL string `json:"regional_cred_verification_url"`
+	CredVerificationURL         string `json:"cred_verification_url"`
+	Format                      format `json:"format"`
+}
+
+// parse determines the type of CredentialSource needed
+func (c *Config) parse(ctx context.Context) (baseCredentialSource, error) {
+	if len(c.CredentialSource.EnvironmentID) > 3 && c.CredentialSource.EnvironmentID[:3] == "aws" {
+		if awsVersion, err := strconv.Atoi(c.CredentialSource.EnvironmentID[3:]); err == nil {
+			if awsVersion != 1 {
+				return nil, fmt.Errorf("oauth2/google: aws version '%d' is not supported in the current build", awsVersion)
+			}
+			return awsCredentialSource{
+				EnvironmentID:               c.CredentialSource.EnvironmentID,
+				RegionURL:                   c.CredentialSource.RegionURL,
+				RegionalCredVerificationURL: c.CredentialSource.RegionalCredVerificationURL,
+				CredVerificationURL:         c.CredentialSource.URL,
+				TargetResource:              c.Audience,
+				ctx:                         ctx,
+			}, nil
+		}
+	} else if c.CredentialSource.File != "" {
+		return fileCredentialSource{File: c.CredentialSource.File, Format: c.CredentialSource.Format}, nil
+	} else if c.CredentialSource.URL != "" {
+		return urlCredentialSource{URL: c.CredentialSource.URL, Headers: c.CredentialSource.Headers, Format: c.CredentialSource.Format, ctx: ctx}, nil
+	}
+	return nil, fmt.Errorf("oauth2/google: unable to parse credential source")
+}
+
+type baseCredentialSource interface {
+	subjectToken() (string, error)
+}
+
+// tokenSource is the source that handles external credentials.
+type tokenSource struct {
+	ctx  context.Context
+	conf *Config
+}
+
+// Token allows tokenSource to conform to the oauth2.TokenSource interface.
+func (ts tokenSource) Token() (*oauth2.Token, error) {
+	conf := ts.conf
+
+	credSource, err := conf.parse(ts.ctx)
+	if err != nil {
+		return nil, err
+	}
+	subjectToken, err := credSource.subjectToken()
+
+	if err != nil {
+		return nil, err
+	}
+	stsRequest := stsTokenExchangeRequest{
+		GrantType:          "urn:ietf:params:oauth:grant-type:token-exchange",
+		Audience:           conf.Audience,
+		Scope:              conf.Scopes,
+		RequestedTokenType: "urn:ietf:params:oauth:token-type:access_token",
+		SubjectToken:       subjectToken,
+		SubjectTokenType:   conf.SubjectTokenType,
+	}
+	header := make(http.Header)
+	header.Add("Content-Type", "application/x-www-form-urlencoded")
+	clientAuth := clientAuthentication{
+		AuthStyle:    oauth2.AuthStyleInHeader,
+		ClientID:     conf.ClientID,
+		ClientSecret: conf.ClientSecret,
+	}
+	stsResp, err := exchangeToken(ts.ctx, conf.TokenURL, &stsRequest, clientAuth, header, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	accessToken := &oauth2.Token{
+		AccessToken: stsResp.AccessToken,
+		TokenType:   stsResp.TokenType,
+	}
+	if stsResp.ExpiresIn < 0 {
+		return nil, fmt.Errorf("oauth2/google: got invalid expiry from security token service")
+	} else if stsResp.ExpiresIn >= 0 {
+		accessToken.Expiry = now().Add(time.Duration(stsResp.ExpiresIn) * time.Second)
+	}
+
+	if stsResp.RefreshToken != "" {
+		accessToken.RefreshToken = stsResp.RefreshToken
+	}
+	return accessToken, nil
+}

+ 41 - 0
vendor/golang.org/x/oauth2/google/internal/externalaccount/clientauth.go

@@ -0,0 +1,41 @@
+// Copyright 2020 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 externalaccount
+
+import (
+	"encoding/base64"
+	"golang.org/x/oauth2"
+	"net/http"
+	"net/url"
+)
+
+// clientAuthentication represents an OAuth client ID and secret and the mechanism for passing these credentials as stated in rfc6749#2.3.1.
+type clientAuthentication struct {
+	// AuthStyle can be either basic or request-body
+	AuthStyle    oauth2.AuthStyle
+	ClientID     string
+	ClientSecret string
+}
+
+func (c *clientAuthentication) InjectAuthentication(values url.Values, headers http.Header) {
+	if c.ClientID == "" || c.ClientSecret == "" || values == nil || headers == nil {
+		return
+	}
+
+	switch c.AuthStyle {
+	case oauth2.AuthStyleInHeader: // AuthStyleInHeader corresponds to basic authentication as defined in rfc7617#2
+		plainHeader := c.ClientID + ":" + c.ClientSecret
+		headers.Add("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(plainHeader)))
+	case oauth2.AuthStyleInParams: // AuthStyleInParams corresponds to request-body authentication with ClientID and ClientSecret in the message body.
+		values.Set("client_id", c.ClientID)
+		values.Set("client_secret", c.ClientSecret)
+	case oauth2.AuthStyleAutoDetect:
+		values.Set("client_id", c.ClientID)
+		values.Set("client_secret", c.ClientSecret)
+	default:
+		values.Set("client_id", c.ClientID)
+		values.Set("client_secret", c.ClientSecret)
+	}
+}

+ 18 - 0
vendor/golang.org/x/oauth2/google/internal/externalaccount/err.go

@@ -0,0 +1,18 @@
+// Copyright 2020 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 externalaccount
+
+import "fmt"
+
+// Error for handling OAuth related error responses as stated in rfc6749#5.2.
+type Error struct {
+	Code        string
+	URI         string
+	Description string
+}
+
+func (err *Error) Error() string {
+	return fmt.Sprintf("got error code %s from %s: %s", err.Code, err.URI, err.Description)
+}

+ 57 - 0
vendor/golang.org/x/oauth2/google/internal/externalaccount/filecredsource.go

@@ -0,0 +1,57 @@
+// Copyright 2020 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 externalaccount
+
+import (
+	"bytes"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+)
+
+type fileCredentialSource struct {
+	File   string
+	Format format
+}
+
+func (cs fileCredentialSource) subjectToken() (string, error) {
+	tokenFile, err := os.Open(cs.File)
+	if err != nil {
+		return "", fmt.Errorf("oauth2/google: failed to open credential file %q", cs.File)
+	}
+	defer tokenFile.Close()
+	tokenBytes, err := ioutil.ReadAll(io.LimitReader(tokenFile, 1<<20))
+	if err != nil {
+		return "", fmt.Errorf("oauth2/google: failed to read credential file: %v", err)
+	}
+	tokenBytes = bytes.TrimSpace(tokenBytes)
+	switch cs.Format.Type {
+	case "json":
+		jsonData := make(map[string]interface{})
+		err = json.Unmarshal(tokenBytes, &jsonData)
+		if err != nil {
+			return "", fmt.Errorf("oauth2/google: failed to unmarshal subject token file: %v", err)
+		}
+		val, ok := jsonData[cs.Format.SubjectTokenFieldName]
+		if !ok {
+			return "", errors.New("oauth2/google: provided subject_token_field_name not found in credentials")
+		}
+		token, ok := val.(string)
+		if !ok {
+			return "", errors.New("oauth2/google: improperly formatted subject token")
+		}
+		return token, nil
+	case "text":
+		return string(tokenBytes), nil
+	case "":
+		return string(tokenBytes), nil
+	default:
+		return "", errors.New("oauth2/google: invalid credential_source file format type")
+	}
+
+}

+ 83 - 0
vendor/golang.org/x/oauth2/google/internal/externalaccount/impersonate.go

@@ -0,0 +1,83 @@
+// Copyright 2021 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 externalaccount
+
+import (
+	"bytes"
+	"context"
+	"encoding/json"
+	"fmt"
+	"golang.org/x/oauth2"
+	"io"
+	"io/ioutil"
+	"net/http"
+	"time"
+)
+
+// generateAccesstokenReq is used for service account impersonation
+type generateAccessTokenReq struct {
+	Delegates []string `json:"delegates,omitempty"`
+	Lifetime  string   `json:"lifetime,omitempty"`
+	Scope     []string `json:"scope,omitempty"`
+}
+
+type impersonateTokenResponse struct {
+	AccessToken string `json:"accessToken"`
+	ExpireTime  string `json:"expireTime"`
+}
+
+type impersonateTokenSource struct {
+	ctx context.Context
+	ts  oauth2.TokenSource
+
+	url    string
+	scopes []string
+}
+
+// Token performs the exchange to get a temporary service account
+func (its impersonateTokenSource) Token() (*oauth2.Token, error) {
+	reqBody := generateAccessTokenReq{
+		Lifetime: "3600s",
+		Scope:    its.scopes,
+	}
+	b, err := json.Marshal(reqBody)
+	if err != nil {
+		return nil, fmt.Errorf("oauth2/google: unable to marshal request: %v", err)
+	}
+	client := oauth2.NewClient(its.ctx, its.ts)
+	req, err := http.NewRequest("POST", its.url, bytes.NewReader(b))
+	if err != nil {
+		return nil, fmt.Errorf("oauth2/google: unable to create impersonation request: %v", err)
+	}
+	req = req.WithContext(its.ctx)
+	req.Header.Set("Content-Type", "application/json")
+
+	resp, err := client.Do(req)
+	if err != nil {
+		return nil, fmt.Errorf("oauth2/google: unable to generate access token: %v", err)
+	}
+	defer resp.Body.Close()
+	body, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1<<20))
+	if err != nil {
+		return nil, fmt.Errorf("oauth2/google: unable to read body: %v", err)
+	}
+	if c := resp.StatusCode; c < 200 || c > 299 {
+		return nil, fmt.Errorf("oauth2/google: status code %d: %s", c, body)
+	}
+
+	var accessTokenResp impersonateTokenResponse
+	if err := json.Unmarshal(body, &accessTokenResp); err != nil {
+		return nil, fmt.Errorf("oauth2/google: unable to parse response: %v", err)
+	}
+	expiry, err := time.Parse(time.RFC3339, accessTokenResp.ExpireTime)
+	if err != nil {
+		return nil, fmt.Errorf("oauth2/google: unable to parse expiry: %v", err)
+	}
+	return &oauth2.Token{
+		AccessToken: accessTokenResp.AccessToken,
+		Expiry:      expiry,
+		TokenType:   "Bearer",
+	}, nil
+}

+ 104 - 0
vendor/golang.org/x/oauth2/google/internal/externalaccount/sts_exchange.go

@@ -0,0 +1,104 @@
+// Copyright 2020 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 externalaccount
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"strconv"
+	"strings"
+
+	"golang.org/x/oauth2"
+)
+
+// exchangeToken performs an oauth2 token exchange with the provided endpoint.
+// The first 4 fields are all mandatory.  headers can be used to pass additional
+// headers beyond the bare minimum required by the token exchange.  options can
+// be used to pass additional JSON-structured options to the remote server.
+func exchangeToken(ctx context.Context, endpoint string, request *stsTokenExchangeRequest, authentication clientAuthentication, headers http.Header, options map[string]interface{}) (*stsTokenExchangeResponse, error) {
+
+	client := oauth2.NewClient(ctx, nil)
+
+	data := url.Values{}
+	data.Set("audience", request.Audience)
+	data.Set("grant_type", "urn:ietf:params:oauth:grant-type:token-exchange")
+	data.Set("requested_token_type", "urn:ietf:params:oauth:token-type:access_token")
+	data.Set("subject_token_type", request.SubjectTokenType)
+	data.Set("subject_token", request.SubjectToken)
+	data.Set("scope", strings.Join(request.Scope, " "))
+	if options != nil {
+		opts, err := json.Marshal(options)
+		if err != nil {
+			return nil, fmt.Errorf("oauth2/google: failed to marshal additional options: %v", err)
+		}
+		data.Set("options", string(opts))
+	}
+
+	authentication.InjectAuthentication(data, headers)
+	encodedData := data.Encode()
+
+	req, err := http.NewRequest("POST", endpoint, strings.NewReader(encodedData))
+	if err != nil {
+		return nil, fmt.Errorf("oauth2/google: failed to properly build http request: %v", err)
+
+	}
+	req = req.WithContext(ctx)
+	for key, list := range headers {
+		for _, val := range list {
+			req.Header.Add(key, val)
+		}
+	}
+	req.Header.Add("Content-Length", strconv.Itoa(len(encodedData)))
+
+	resp, err := client.Do(req)
+
+	if err != nil {
+		return nil, fmt.Errorf("oauth2/google: invalid response from Secure Token Server: %v", err)
+	}
+	defer resp.Body.Close()
+
+	body, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1<<20))
+	if c := resp.StatusCode; c < 200 || c > 299 {
+		return nil, fmt.Errorf("oauth2/google: status code %d: %s", c, body)
+	}
+	var stsResp stsTokenExchangeResponse
+	err = json.Unmarshal(body, &stsResp)
+	if err != nil {
+		return nil, fmt.Errorf("oauth2/google: failed to unmarshal response body from Secure Token Server: %v", err)
+
+	}
+
+	return &stsResp, nil
+}
+
+// stsTokenExchangeRequest contains fields necessary to make an oauth2 token exchange.
+type stsTokenExchangeRequest struct {
+	ActingParty struct {
+		ActorToken     string
+		ActorTokenType string
+	}
+	GrantType          string
+	Resource           string
+	Audience           string
+	Scope              []string
+	RequestedTokenType string
+	SubjectToken       string
+	SubjectTokenType   string
+}
+
+// stsTokenExchangeResponse is used to decode the remote server response during an oauth2 token exchange.
+type stsTokenExchangeResponse struct {
+	AccessToken     string `json:"access_token"`
+	IssuedTokenType string `json:"issued_token_type"`
+	TokenType       string `json:"token_type"`
+	ExpiresIn       int    `json:"expires_in"`
+	Scope           string `json:"scope"`
+	RefreshToken    string `json:"refresh_token"`
+}

+ 74 - 0
vendor/golang.org/x/oauth2/google/internal/externalaccount/urlcredsource.go

@@ -0,0 +1,74 @@
+// Copyright 2020 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 externalaccount
+
+import (
+	"context"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"golang.org/x/oauth2"
+	"io"
+	"io/ioutil"
+	"net/http"
+)
+
+type urlCredentialSource struct {
+	URL     string
+	Headers map[string]string
+	Format  format
+	ctx     context.Context
+}
+
+func (cs urlCredentialSource) subjectToken() (string, error) {
+	client := oauth2.NewClient(cs.ctx, nil)
+	req, err := http.NewRequest("GET", cs.URL, nil)
+	if err != nil {
+		return "", fmt.Errorf("oauth2/google: HTTP request for URL-sourced credential failed: %v", err)
+	}
+	req = req.WithContext(cs.ctx)
+
+	for key, val := range cs.Headers {
+		req.Header.Add(key, val)
+	}
+	resp, err := client.Do(req)
+	if err != nil {
+		return "", fmt.Errorf("oauth2/google: invalid response when retrieving subject token: %v", err)
+	}
+	defer resp.Body.Close()
+
+	respBody, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1<<20))
+	if err != nil {
+		return "", fmt.Errorf("oauth2/google: invalid body in subject token URL query: %v", err)
+	}
+	if c := resp.StatusCode; c < 200 || c > 299 {
+		return "", fmt.Errorf("oauth2/google: status code %d: %s", c, respBody)
+	}
+
+	switch cs.Format.Type {
+	case "json":
+		jsonData := make(map[string]interface{})
+		err = json.Unmarshal(respBody, &jsonData)
+		if err != nil {
+			return "", fmt.Errorf("oauth2/google: failed to unmarshal subject token file: %v", err)
+		}
+		val, ok := jsonData[cs.Format.SubjectTokenFieldName]
+		if !ok {
+			return "", errors.New("oauth2/google: provided subject_token_field_name not found in credentials")
+		}
+		token, ok := val.(string)
+		if !ok {
+			return "", errors.New("oauth2/google: improperly formatted subject token")
+		}
+		return token, nil
+	case "text":
+		return string(respBody), nil
+	case "":
+		return string(respBody), nil
+	default:
+		return "", errors.New("oauth2/google: invalid credential_source file format type")
+	}
+
+}

+ 1 - 0
vendor/golang.org/x/oauth2/internal/client_appengine.go

@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+//go:build appengine
 // +build appengine
 
 package internal

+ 3 - 2
vendor/modules.txt

@@ -828,10 +828,12 @@ golang.org/x/net/ipv6
 golang.org/x/net/proxy
 golang.org/x/net/trace
 golang.org/x/net/websocket
-# golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c => golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
+# golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c
 ## explicit; go 1.11
 golang.org/x/oauth2
+golang.org/x/oauth2/authhandler
 golang.org/x/oauth2/google
+golang.org/x/oauth2/google/internal/externalaccount
 golang.org/x/oauth2/internal
 golang.org/x/oauth2/jws
 golang.org/x/oauth2/jwt
@@ -1002,7 +1004,6 @@ gotest.tools/v3/skip
 # github.com/prometheus/procfs => github.com/prometheus/procfs v0.0.11
 # github.com/vishvananda/netlink => github.com/vishvananda/netlink v1.1.0
 # go.opencensus.io => go.opencensus.io v0.22.3
-# golang.org/x/oauth2 => golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
 # google.golang.org/api => google.golang.org/api v0.8.0
 # google.golang.org/genproto => google.golang.org/genproto v0.0.0-20200227132054-3f1135a288c9
 # google.golang.org/grpc => google.golang.org/grpc v1.27.1