From bb43161e2f72d9aeeb3ba8ae43ab150f034b7ba4 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Fri, 23 Jan 2026 16:49:30 +0100 Subject: [PATCH] vendor: google.golang.org/api v0.260.0 Signed-off-by: Sebastiaan van Stijn --- go.mod | 4 +- go.sum | 8 +- .../api/googleapi/googleapi.go | 15 ++ .../credentialstype/credentialstype.go | 113 ++++++++++++++ .../google.golang.org/api/internal/creds.go | 26 ++-- .../api/internal/settings.go | 67 ++++++-- .../google.golang.org/api/internal/version.go | 2 +- .../option/internaloption/internaloption.go | 4 +- vendor/google.golang.org/api/option/option.go | 143 ++++++++++++++++-- .../api/transport/grpc/dial.go | 30 +--- .../api/transport/http/dial.go | 6 +- vendor/modules.txt | 5 +- 12 files changed, 355 insertions(+), 68 deletions(-) create mode 100644 vendor/google.golang.org/api/internal/credentialstype/credentialstype.go diff --git a/go.mod b/go.mod index fdad041b87..7d6aa5ab15 100644 --- a/go.mod +++ b/go.mod @@ -292,9 +292,9 @@ require ( golang.org/x/oauth2 v0.34.0 // indirect golang.org/x/term v0.38.0 // indirect golang.org/x/tools v0.40.0 // indirect - google.golang.org/api v0.257.0 // indirect + google.golang.org/api v0.260.0 // indirect google.golang.org/genproto v0.0.0-20251202230838-ff82c1b0f217 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b // indirect gopkg.in/yaml.v3 v3.0.1 // indirect sigs.k8s.io/yaml v1.6.0 // indirect tags.cncf.io/container-device-interface/specs-go v1.1.0 // indirect diff --git a/go.sum b/go.sum index e55bb7c947..cf0d0694d5 100644 --- a/go.sum +++ b/go.sum @@ -990,8 +990,8 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= google.golang.org/api v0.0.0-20170921000349-586095a6e407/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.257.0 h1:8Y0lzvHlZps53PEaw+G29SsQIkuKrumGWs9puiexNAA= -google.golang.org/api v0.257.0/go.mod h1:4eJrr+vbVaZSqs7vovFd1Jb/A6ml6iw2e6FBYf3GAO4= +google.golang.org/api v0.260.0 h1:XbNi5E6bOVEj/uLXQRlt6TKuEzMD7zvW/6tNwltE4P4= +google.golang.org/api v0.260.0/go.mod h1:Shj1j0Phr/9sloYrKomICzdYgsSDImpTxME8rGLaZ/o= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= @@ -1003,8 +1003,8 @@ google.golang.org/genproto v0.0.0-20251202230838-ff82c1b0f217 h1:GvESR9BIyHUahIb google.golang.org/genproto v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:yJ2HH4EHEDTd3JiLmhds6NkJ17ITVYOdV3m3VKOnws0= google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 h1:fCvbg86sFXwdrl5LgVcTEvNC+2txB5mgROGmRL5mrls= google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:+rXWjjaukWZun3mLfjmVnQi18E1AsFbDN9QdJ5YXLto= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b h1:Mv8VFug0MP9e5vUxfBcE3vUkV6CImK3cMNMIDFjmzxU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= google.golang.org/grpc v1.2.1-0.20170921194603-d4b75ebd4f9f/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= diff --git a/vendor/google.golang.org/api/googleapi/googleapi.go b/vendor/google.golang.org/api/googleapi/googleapi.go index f8a85d5a47..167f061092 100644 --- a/vendor/google.golang.org/api/googleapi/googleapi.go +++ b/vendor/google.golang.org/api/googleapi/googleapi.go @@ -333,6 +333,20 @@ func ChunkRetryDeadline(deadline time.Duration) MediaOption { return chunkRetryDeadlineOption(deadline) } +type enableAutoChecksumOption struct{} + +func (d enableAutoChecksumOption) setOptions(o *MediaOptions) { + o.EnableAutoChecksum = true +} + +// EnableAutoChecksum returns a MediaOption that enables automatic checksum +// calculation, which is only supported for resumable multi-chunk uploads. +// The computed checksum is sent on the final upload request to the server. +// Writes are rejected in the event of a checksum mismatch. +func EnableAutoChecksum() MediaOption { + return enableAutoChecksumOption{} +} + // MediaOptions stores options for customizing media upload. It is not used by developers directly. type MediaOptions struct { ContentType string @@ -340,6 +354,7 @@ type MediaOptions struct { ChunkSize int ChunkRetryDeadline time.Duration ChunkTransferTimeout time.Duration + EnableAutoChecksum bool } // ProcessMediaOptions stores options from opts in a MediaOptions. diff --git a/vendor/google.golang.org/api/internal/credentialstype/credentialstype.go b/vendor/google.golang.org/api/internal/credentialstype/credentialstype.go new file mode 100644 index 0000000000..0e2c4612c8 --- /dev/null +++ b/vendor/google.golang.org/api/internal/credentialstype/credentialstype.go @@ -0,0 +1,113 @@ +// Copyright 2024 Google LLC. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package credentialstype defines the CredType used for specifying the type of JSON credentials. +package credentialstype + +import ( + "encoding/json" + "fmt" + "slices" +) + +// CredType specifies the type of JSON credentials. +type CredType string + +const ( + // Unknown represents an unknown JSON file type. + Unknown CredType = "" + // ServiceAccount represents a service account file type. + ServiceAccount CredType = "service_account" + // AuthorizedUser represents an authorized user credentials file type. + AuthorizedUser CredType = "authorized_user" + // ImpersonatedServiceAccount represents an impersonated service account file type. + // + // IMPORTANT: + // This credential type does not validate the credential configuration. A security + // risk occurs when a credential configuration configured with malicious urls + // is used. + // You should validate credential configurations provided by untrusted sources. + // See [Security requirements when using credential configurations from an external + // source] https://cloud.google.com/docs/authentication/external/externally-sourced-credentials + // for more details. + ImpersonatedServiceAccount CredType = "impersonated_service_account" + // ExternalAccount represents an external account file type. + // + // IMPORTANT: + // This credential type does not validate the credential configuration. A security + // risk occurs when a credential configuration configured with malicious urls + // is used. + // You should validate credential configurations provided by untrusted sources. + // See [Security requirements when using credential configurations from an external + // source] https://cloud.google.com/docs/authentication/external/externally-sourced-credentials + // for more details. + ExternalAccount CredType = "external_account" + // GDCHServiceAccount represents a GDCH service account file type. + GDCHServiceAccount CredType = "gdc_service_account" + // ExternalAccountAuthorizedUser represents an external account authorized user file type. + ExternalAccountAuthorizedUser CredType = "external_account_authorized_user" +) + +var knownTypes = map[CredType]bool{ + ServiceAccount: true, + AuthorizedUser: true, + ImpersonatedServiceAccount: true, + ExternalAccount: true, + GDCHServiceAccount: true, + ExternalAccountAuthorizedUser: true, +} + +// GetCredType returns the credentials type or the Unknown type, +// or an error for empty data or failure to unmarshal JSON. +func GetCredType(data []byte) (CredType, error) { + var t CredType + if len(data) == 0 { + return t, fmt.Errorf("credential provided is 0 bytes") + } + var f struct { + Type string `json:"type"` + } + if err := json.Unmarshal(data, &f); err != nil { + return t, err + } + t = parseCredType(f.Type) + return t, nil +} + +// CheckCredentialType checks if the provided JSON bytes match the expected +// credential type and, if present, one of the allowed credential types. +// An error is returned if the JSON is invalid, the type field is missing, +// or the types do not match expected and (if present) allowed. +func CheckCredentialType(b []byte, expected CredType, allowed ...CredType) error { + var f struct { + Type string `json:"type"` + } + if err := json.Unmarshal(b, &f); err != nil { + return fmt.Errorf("unable to parse credential type: %w", err) + } + if f.Type == "" { + return fmt.Errorf("missing `type` field in credential") + } + credType := CredType(f.Type) + if credType != expected { + return fmt.Errorf("credential type mismatch: got %q, expected %q", credType, expected) + } + if len(allowed) == 0 { + return nil + } + if !slices.Contains(allowed, credType) { + return fmt.Errorf("credential type not allowed: %q", credType) + } + return nil +} + +// parseCredType returns the matching CredType for the JSON type string if +// it is in the list of publicly exposed types, otherwise Unknown. +func parseCredType(typeString string) CredType { + ct := CredType(typeString) + if knownTypes[ct] { + return ct + } + return Unknown +} diff --git a/vendor/google.golang.org/api/internal/creds.go b/vendor/google.golang.org/api/internal/creds.go index 92bb42c321..2172ba4395 100644 --- a/vendor/google.golang.org/api/internal/creds.go +++ b/vendor/google.golang.org/api/internal/creds.go @@ -20,6 +20,7 @@ import ( "cloud.google.com/go/auth/oauth2adapt" "golang.org/x/oauth2" "google.golang.org/api/internal/cert" + "google.golang.org/api/internal/credentialstype" "google.golang.org/api/internal/impersonate" "golang.org/x/oauth2/google" @@ -139,11 +140,13 @@ func detectDefaultFromDialSettings(settings *DialSettings) (*auth.Credentials, e aud = settings.DefaultAudience } + credsFile, _ := settings.GetAuthCredentialsFile() + credsJSON, _ := settings.GetAuthCredentialsJSON() return credentials.DetectDefault(&credentials.DetectOptions{ Scopes: scopes, Audience: aud, - CredentialsFile: settings.CredentialsFile, - CredentialsJSON: settings.CredentialsJSON, + CredentialsFile: credsFile, + CredentialsJSON: credsJSON, UseSelfSignedJWT: useSelfSignedJWT, Logger: settings.Logger, }) @@ -156,15 +159,15 @@ func baseCreds(ctx context.Context, ds *DialSettings) (*google.Credentials, erro if ds.Credentials != nil { return ds.Credentials, nil } - if len(ds.CredentialsJSON) > 0 { - return credentialsFromJSON(ctx, ds.CredentialsJSON, ds) + if credsJSON, checkCredType := ds.GetAuthCredentialsJSON(); len(credsJSON) > 0 { + return credentialsFromJSON(ctx, credsJSON, ds, checkCredType) } - if ds.CredentialsFile != "" { - data, err := os.ReadFile(ds.CredentialsFile) + if credsFile, checkCredType := ds.GetAuthCredentialsFile(); credsFile != "" { + data, err := os.ReadFile(credsFile) if err != nil { return nil, fmt.Errorf("cannot read credentials file: %v", err) } - return credentialsFromJSON(ctx, data, ds) + return credentialsFromJSON(ctx, data, ds, checkCredType) } if ds.TokenSource != nil { return &google.Credentials{TokenSource: ds.TokenSource}, nil @@ -174,7 +177,7 @@ func baseCreds(ctx context.Context, ds *DialSettings) (*google.Credentials, erro return nil, err } if len(cred.JSON) > 0 { - return credentialsFromJSON(ctx, cred.JSON, ds) + return credentialsFromJSON(ctx, cred.JSON, ds, credentialstype.Unknown) } // For GAE and GCE, the JSON is empty so return the default credentials directly. return cred, nil @@ -197,7 +200,12 @@ const ( // // - Otherwise, executes standard OAuth 2.0 flow // More details: google.aip.dev/auth/4111 -func credentialsFromJSON(ctx context.Context, data []byte, ds *DialSettings) (*google.Credentials, error) { +func credentialsFromJSON(ctx context.Context, data []byte, ds *DialSettings, checkCredType credentialstype.CredType) (*google.Credentials, error) { + if checkCredType != credentialstype.Unknown { + if err := credentialstype.CheckCredentialType(data, checkCredType); err != nil { + return nil, err + } + } var params google.CredentialsParams params.Scopes = ds.GetScopes() diff --git a/vendor/google.golang.org/api/internal/settings.go b/vendor/google.golang.org/api/internal/settings.go index a81d149ae2..96a5fc3be1 100644 --- a/vendor/google.golang.org/api/internal/settings.go +++ b/vendor/google.golang.org/api/internal/settings.go @@ -17,6 +17,7 @@ import ( "cloud.google.com/go/auth" "golang.org/x/oauth2" "golang.org/x/oauth2/google" + "google.golang.org/api/internal/credentialstype" "google.golang.org/api/internal/impersonate" "google.golang.org/grpc" ) @@ -31,16 +32,18 @@ const ( // DialSettings holds information needed to establish a connection with a // Google API service. type DialSettings struct { - Endpoint string - DefaultEndpoint string - DefaultEndpointTemplate string - DefaultMTLSEndpoint string - Scopes []string - DefaultScopes []string - EnableJwtWithScope bool - TokenSource oauth2.TokenSource - Credentials *google.Credentials - CredentialsFile string // if set, Token Source is ignored. + Endpoint string + DefaultEndpoint string + DefaultEndpointTemplate string + DefaultMTLSEndpoint string + Scopes []string + DefaultScopes []string + EnableJwtWithScope bool + TokenSource oauth2.TokenSource + Credentials *google.Credentials + // Deprecated: Use AuthCredentialsFile instead, due to security risk. + CredentialsFile string + // Deprecated: Use AuthCredentialsJSON instead, due to security risk. CredentialsJSON []byte InternalCredentials *google.Credentials UserAgent string @@ -72,6 +75,9 @@ type DialSettings struct { // New Auth library Options AuthCredentials *auth.Credentials + AuthCredentialsJSON []byte + AuthCredentialsFile string + AuthCredentialsType credentialstype.CredType EnableNewAuthLibrary bool // TODO(b/372244283): Remove after b/358175516 has been fixed @@ -113,22 +119,55 @@ func (ds *DialSettings) IsNewAuthLibraryEnabled() bool { if ds.AuthCredentials != nil { return true } + if len(ds.AuthCredentialsJSON) > 0 { + return true + } + if ds.AuthCredentialsFile != "" { + return true + } if b, err := strconv.ParseBool(os.Getenv(newAuthLibEnvVar)); err == nil { return b } return false } +// GetAuthCredentialsJSON returns the AuthCredentialsJSON and AuthCredentialsType, if set. +// Otherwise it falls back to the deprecated CredentialsJSON with an Unknown type. +// +// Use AuthCredentialsJSON if provided, as it is the safer, recommended option. +// CredentialsJSON is populated by the deprecated WithCredentialsJSON. +func (ds *DialSettings) GetAuthCredentialsJSON() ([]byte, credentialstype.CredType) { + if len(ds.AuthCredentialsJSON) > 0 { + return ds.AuthCredentialsJSON, ds.AuthCredentialsType + } + return ds.CredentialsJSON, credentialstype.Unknown +} + +// GetAuthCredentialsFile returns the AuthCredentialsFile and AuthCredentialsType, if set. +// Otherwise it falls back to the deprecated CredentialsFile with an Unknown type. +// +// Use AuthCredentialsFile if provided, as it is the safer, recommended option. +// CredentialsFile is populated by the deprecated WithCredentialsFile. +func (ds *DialSettings) GetAuthCredentialsFile() (string, credentialstype.CredType) { + if ds.AuthCredentialsFile != "" { + return ds.AuthCredentialsFile, ds.AuthCredentialsType + } + return ds.CredentialsFile, credentialstype.Unknown +} + // Validate reports an error if ds is invalid. func (ds *DialSettings) Validate() error { if ds.SkipValidation { return nil } - hasCreds := ds.APIKey != "" || ds.TokenSource != nil || ds.CredentialsFile != "" || ds.Credentials != nil + hasCreds := ds.APIKey != "" || ds.TokenSource != nil || ds.CredentialsFile != "" || ds.Credentials != nil || ds.AuthCredentials != nil || len(ds.AuthCredentialsJSON) > 0 || ds.AuthCredentialsFile != "" if ds.NoAuth && hasCreds { return errors.New("options.WithoutAuthentication is incompatible with any option that provides credentials") } // Credentials should not appear with other options. + // AuthCredentials is a special case that may be present with + // with other options in order to facilitate automatic conversion of + // oauth2 types (old auth) to cloud.google.com/go/auth types (new auth). // We currently allow TokenSource and CredentialsFile to coexist. // TODO(jba): make TokenSource & CredentialsFile an error (breaking change). nCreds := 0 @@ -138,6 +177,12 @@ func (ds *DialSettings) Validate() error { if len(ds.CredentialsJSON) > 0 { nCreds++ } + if len(ds.AuthCredentialsJSON) > 0 { + nCreds++ + } + if ds.AuthCredentialsFile != "" { + nCreds++ + } if ds.CredentialsFile != "" { nCreds++ } diff --git a/vendor/google.golang.org/api/internal/version.go b/vendor/google.golang.org/api/internal/version.go index 6368b1d5cc..1cbe3157f1 100644 --- a/vendor/google.golang.org/api/internal/version.go +++ b/vendor/google.golang.org/api/internal/version.go @@ -5,4 +5,4 @@ package internal // Version is the current tagged release of the library. -const Version = "0.257.0" +const Version = "0.260.0" diff --git a/vendor/google.golang.org/api/option/internaloption/internaloption.go b/vendor/google.golang.org/api/option/internaloption/internaloption.go index 931f093d89..d67351a7fa 100644 --- a/vendor/google.golang.org/api/option/internaloption/internaloption.go +++ b/vendor/google.golang.org/api/option/internaloption/internaloption.go @@ -290,7 +290,7 @@ func GetLogger(opts []option.ClientOption) *slog.Logger { // options, in this order: // // - [option.WithoutAuthentication] -// - [option.WithAuthCredentials] +// - [option.Credentials] // - [WithCredentials] (internal use only) // - [option.WithCredentials] // - [option.WithTokenSource] @@ -300,7 +300,9 @@ func GetLogger(opts []option.ClientOption) *slog.Logger { // returns the result: // // - [option.WithAudiences] +// - [option.WithAuthCredentialsFile] // - [option.WithCredentialsFile] +// - [option.WithAuthCredentialsJSON] // - [option.WithCredentialsJSON] // - [option.WithScopes] // - [WithDefaultScopes] (internal use only) diff --git a/vendor/google.golang.org/api/option/option.go b/vendor/google.golang.org/api/option/option.go index 1b134caa86..4dbfc3a2ab 100644 --- a/vendor/google.golang.org/api/option/option.go +++ b/vendor/google.golang.org/api/option/option.go @@ -14,10 +14,45 @@ import ( "golang.org/x/oauth2" "golang.org/x/oauth2/google" "google.golang.org/api/internal" + "google.golang.org/api/internal/credentialstype" "google.golang.org/api/internal/impersonate" "google.golang.org/grpc" ) +// CredentialsType specifies the type of JSON credentials being provided +// to a loading function such as [WithAuthCredentialsFile] or +// [WithAuthCredentialsJSON]. +type CredentialsType = credentialstype.CredType + +const ( + // ServiceAccount represents a service account file type. + ServiceAccount = credentialstype.ServiceAccount + // AuthorizedUser represents an authorized user credentials file type. + AuthorizedUser = credentialstype.AuthorizedUser + // ImpersonatedServiceAccount represents an impersonated service account file type. + // + // IMPORTANT: + // This credential type does not validate the credential configuration. A security + // risk occurs when a credential configuration configured with malicious urls + // is used. + // You should validate credential configurations provided by untrusted sources. + // See [Security requirements when using credential configurations from an external + // source] https://cloud.google.com/docs/authentication/external/externally-sourced-credentials + // for more details. + ImpersonatedServiceAccount = credentialstype.ImpersonatedServiceAccount + // ExternalAccount represents an external account file type. + // + // IMPORTANT: + // This credential type does not validate the credential configuration. A security + // risk occurs when a credential configuration configured with malicious urls + // is used. + // You should validate credential configurations provided by untrusted sources. + // See [Security requirements when using credential configurations from an external + // source] https://cloud.google.com/docs/authentication/external/externally-sourced-credentials + // for more details. + ExternalAccount = credentialstype.ExternalAccount +) + // A ClientOption is an option for a Google API client. type ClientOption interface { Apply(*internal.DialSettings) @@ -45,6 +80,36 @@ func (w withCredFile) Apply(o *internal.DialSettings) { // API calls with the given service account or refresh token JSON // credentials file. // +// Deprecated: This function is being deprecated because of a potential security risk. +// +// This function does not validate the credential configuration. The security +// risk occurs when a credential configuration is accepted from a source that +// is not under your control and used without validation on your side. +// +// If you know that you will be loading credential configurations of a +// specific type, it is recommended to use a credential-type-specific +// option function. +// This will ensure that an unexpected credential type with potential for +// malicious intent is not loaded unintentionally. You might still have to do +// validation for certain credential types. Please follow the recommendation +// for that function. For example, if you want to load only service accounts, +// you can use [WithAuthCredentialsFile] with [ServiceAccount]: +// +// option.WithAuthCredentialsFile(option.ServiceAccount, "/path/to/file.json") +// +// If you are loading your credential configuration from an untrusted source and have +// not mitigated the risks (e.g. by validating the configuration yourself), make +// these changes as soon as possible to prevent security risks to your environment. +// +// Regardless of the function used, it is always your responsibility to validate +// configurations received from external sources. +func WithCredentialsFile(filename string) ClientOption { + return withCredFile(filename) +} + +// WithAuthCredentialsFile returns a ClientOption that authenticates API calls +// with the given JSON credentials file and credential type. +// // Important: If you accept a credential configuration (credential // JSON/File/Stream) from an external source for authentication to Google // Cloud Platform, you must validate it before providing it to any Google @@ -52,8 +117,21 @@ func (w withCredFile) Apply(o *internal.DialSettings) { // Google APIs can compromise the security of your systems and data. For // more information, refer to [Validate credential configurations from // external sources](https://cloud.google.com/docs/authentication/external/externally-sourced-credentials). -func WithCredentialsFile(filename string) ClientOption { - return withCredFile(filename) +func WithAuthCredentialsFile(credType CredentialsType, filename string) ClientOption { + return withAuthCredentialsFile{ + credsType: credType, + filename: filename, + } +} + +type withAuthCredentialsFile struct { + credsType CredentialsType + filename string +} + +func (w withAuthCredentialsFile) Apply(o *internal.DialSettings) { + o.AuthCredentialsFile = w.filename + o.AuthCredentialsType = w.credsType } // WithServiceAccountFile returns a ClientOption that uses a Google service @@ -67,22 +145,38 @@ func WithCredentialsFile(filename string) ClientOption { // more information, refer to [Validate credential configurations from // external sources](https://cloud.google.com/docs/authentication/external/externally-sourced-credentials). // -// Deprecated: Use WithCredentialsFile instead. +// Deprecated: Use WithAuthCredentialsFile instead. func WithServiceAccountFile(filename string) ClientOption { - return WithCredentialsFile(filename) + return WithAuthCredentialsFile(ServiceAccount, filename) } // WithCredentialsJSON returns a ClientOption that authenticates // API calls with the given service account or refresh token JSON // credentials. // -// Important: If you accept a credential configuration (credential -// JSON/File/Stream) from an external source for authentication to Google -// Cloud Platform, you must validate it before providing it to any Google -// API or library. Providing an unvalidated credential configuration to -// Google APIs can compromise the security of your systems and data. For -// more information, refer to [Validate credential configurations from -// external sources](https://cloud.google.com/docs/authentication/external/externally-sourced-credentials). +// Deprecated: This function is being deprecated because of a potential security risk. +// +// This function does not validate the credential configuration. The security +// risk occurs when a credential configuration is accepted from a source that +// is not under your control and used without validation on your side. +// +// If you know that you will be loading credential configurations of a +// specific type, it is recommended to use a credential-type-specific +// option function. +// This will ensure that an unexpected credential type with potential for +// malicious intent is not loaded unintentionally. You might still have to do +// validation for certain credential types. Please follow the recommendation +// for that function. For example, if you want to load only service accounts, +// you can use [WithAuthCredentialsJSON] with [ServiceAccount]: +// +// option.WithAuthCredentialsJSON(option.ServiceAccount, json) +// +// If you are loading your credential configuration from an untrusted source and have +// not mitigated the risks (e.g. by validating the configuration yourself), make +// these changes as soon as possible to prevent security risks to your environment. +// +// Regardless of the function used, it is always your responsibility to validate +// configurations received from external sources. func WithCredentialsJSON(p []byte) ClientOption { return withCredentialsJSON(p) } @@ -94,6 +188,33 @@ func (w withCredentialsJSON) Apply(o *internal.DialSettings) { copy(o.CredentialsJSON, w) } +// WithAuthCredentialsJSON returns a ClientOption that authenticates API calls +// with the given JSON credentials and credential type. +// +// Important: If you accept a credential configuration (credential +// JSON/File/Stream) from an external source for authentication to Google +// Cloud Platform, you must validate it before providing it to any Google +// API or library. Providing an unvalidated credential configuration to +// Google APIs can compromise the security of your systems and data. For +// more information, refer to [Validate credential configurations from +// external sources](https://cloud.google.com/docs/authentication/external/externally-sourced-credentials). +func WithAuthCredentialsJSON(credType CredentialsType, json []byte) ClientOption { + return withAuthCredentialsJSON{ + credsType: credType, + json: json, + } +} + +type withAuthCredentialsJSON struct { + credsType CredentialsType + json []byte +} + +func (w withAuthCredentialsJSON) Apply(o *internal.DialSettings) { + o.AuthCredentialsJSON = w.json + o.AuthCredentialsType = w.credsType +} + // WithEndpoint returns a ClientOption that overrides the default endpoint // to be used for a service. Please note that by default Google APIs only // accept HTTPS traffic. diff --git a/vendor/google.golang.org/api/transport/grpc/dial.go b/vendor/google.golang.org/api/transport/grpc/dial.go index a6630a0e44..a39a20f1a0 100644 --- a/vendor/google.golang.org/api/transport/grpc/dial.go +++ b/vendor/google.golang.org/api/transport/grpc/dial.go @@ -14,7 +14,6 @@ import ( "net" "os" "strings" - "sync" "time" "cloud.google.com/go/auth" @@ -31,7 +30,6 @@ import ( grpcgoogle "google.golang.org/grpc/credentials/google" grpcinsecure "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/credentials/oauth" - "google.golang.org/grpc/stats" // Install grpclb, which is required for direct path. _ "google.golang.org/grpc/balancer/grpclb" @@ -55,26 +53,6 @@ var dialContext = grpc.DialContext // Assign to var for unit test replacement var dialContextNewAuth = grpctransport.Dial -// otelStatsHandler is a singleton otelgrpc.clientHandler to be used across -// all dial connections to avoid the memory leak documented in -// https://github.com/open-telemetry/opentelemetry-go-contrib/issues/4226 -// -// TODO: If 4226 has been fixed in opentelemetry-go-contrib, replace this -// singleton with inline usage for simplicity. -var ( - initOtelStatsHandlerOnce sync.Once - otelStatsHandler stats.Handler -) - -// otelGRPCStatsHandler returns singleton otelStatsHandler for reuse across all -// dial connections. -func otelGRPCStatsHandler() stats.Handler { - initOtelStatsHandlerOnce.Do(func() { - otelStatsHandler = otelgrpc.NewClientHandler() - }) - return otelStatsHandler -} - // Dial returns a GRPC connection for use communicating with a Google cloud // service, configured with the given ClientOptions. func Dial(ctx context.Context, opts ...option.ClientOption) (*grpc.ClientConn, error) { @@ -220,6 +198,8 @@ func dialPoolNewAuth(ctx context.Context, secure bool, poolSize int, ds *interna defaultEndpointTemplate = ds.DefaultEndpoint } + credsJSON, _ := ds.GetAuthCredentialsJSON() + credsFile, _ := ds.GetAuthCredentialsFile() pool, err := dialContextNewAuth(ctx, secure, &grpctransport.Options{ DisableTelemetry: ds.TelemetryDisabled, DisableAuthentication: ds.NoAuth, @@ -233,8 +213,8 @@ func dialPoolNewAuth(ctx context.Context, secure bool, poolSize int, ds *interna DetectOpts: &credentials.DetectOptions{ Scopes: ds.Scopes, Audience: aud, - CredentialsFile: ds.CredentialsFile, - CredentialsJSON: ds.CredentialsJSON, + CredentialsFile: credsFile, + CredentialsJSON: credsJSON, Logger: ds.Logger, }, InternalOptions: &grpctransport.InternalOptions{ @@ -400,7 +380,7 @@ func addOpenTelemetryStatsHandler(opts []grpc.DialOption, settings *internal.Dia if settings.TelemetryDisabled { return opts } - return append(opts, grpc.WithStatsHandler(otelGRPCStatsHandler())) + return append(opts, grpc.WithStatsHandler(otelgrpc.NewClientHandler())) } // grpcTokenSource supplies PerRPCCredentials from an oauth.TokenSource. diff --git a/vendor/google.golang.org/api/transport/http/dial.go b/vendor/google.golang.org/api/transport/http/dial.go index a33df91203..494de475e5 100644 --- a/vendor/google.golang.org/api/transport/http/dial.go +++ b/vendor/google.golang.org/api/transport/http/dial.go @@ -108,6 +108,8 @@ func newClientNewAuth(ctx context.Context, base http.RoundTripper, ds *internal. if ds.UserAgent != "" { headers.Set("User-Agent", ds.UserAgent) } + credsJSON, _ := ds.GetAuthCredentialsJSON() + credsFile, _ := ds.GetAuthCredentialsFile() client, err := httptransport.NewClient(&httptransport.Options{ DisableTelemetry: ds.TelemetryDisabled, DisableAuthentication: ds.NoAuth, @@ -120,8 +122,8 @@ func newClientNewAuth(ctx context.Context, base http.RoundTripper, ds *internal. DetectOpts: &credentials.DetectOptions{ Scopes: ds.Scopes, Audience: aud, - CredentialsFile: ds.CredentialsFile, - CredentialsJSON: ds.CredentialsJSON, + CredentialsFile: credsFile, + CredentialsJSON: credsJSON, Logger: ds.Logger, }, InternalOptions: &httptransport.InternalOptions{ diff --git a/vendor/modules.txt b/vendor/modules.txt index 1c77e63ea7..0ced58f6ca 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1929,12 +1929,13 @@ golang.org/x/tools/internal/stdlib golang.org/x/tools/internal/typeparams golang.org/x/tools/internal/typesinternal golang.org/x/tools/internal/versions -# google.golang.org/api v0.257.0 +# google.golang.org/api v0.260.0 ## explicit; go 1.24.0 google.golang.org/api/googleapi google.golang.org/api/googleapi/transport google.golang.org/api/internal google.golang.org/api/internal/cert +google.golang.org/api/internal/credentialstype google.golang.org/api/internal/impersonate google.golang.org/api/internal/third_party/uritemplates google.golang.org/api/iterator @@ -1955,7 +1956,7 @@ google.golang.org/genproto/googleapis/api/httpbody google.golang.org/genproto/googleapis/api/label google.golang.org/genproto/googleapis/api/metric google.golang.org/genproto/googleapis/api/monitoredres -# google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 +# google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b ## explicit; go 1.24.0 google.golang.org/genproto/googleapis/rpc/code google.golang.org/genproto/googleapis/rpc/errdetails