1// Copyright 2017 Google LLC. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// Package internal supports the options and transport packages. 6package internal 7 8import ( 9 "crypto/tls" 10 "errors" 11 "net/http" 12 13 "golang.org/x/oauth2" 14 "golang.org/x/oauth2/google" 15 "google.golang.org/api/internal/impersonate" 16 "google.golang.org/grpc" 17) 18 19// DialSettings holds information needed to establish a connection with a 20// Google API service. 21type DialSettings struct { 22 Endpoint string 23 DefaultEndpoint string 24 DefaultMTLSEndpoint string 25 Scopes []string 26 TokenSource oauth2.TokenSource 27 Credentials *google.Credentials 28 CredentialsFile string // if set, Token Source is ignored. 29 CredentialsJSON []byte 30 UserAgent string 31 APIKey string 32 Audiences []string 33 HTTPClient *http.Client 34 GRPCDialOpts []grpc.DialOption 35 GRPCConn *grpc.ClientConn 36 GRPCConnPool ConnPool 37 GRPCConnPoolSize int 38 NoAuth bool 39 TelemetryDisabled bool 40 ClientCertSource func(*tls.CertificateRequestInfo) (*tls.Certificate, error) 41 CustomClaims map[string]interface{} 42 SkipValidation bool 43 ImpersonationConfig *impersonate.Config 44 45 // Google API system parameters. For more information please read: 46 // https://cloud.google.com/apis/docs/system-parameters 47 QuotaProject string 48 RequestReason string 49} 50 51// Validate reports an error if ds is invalid. 52func (ds *DialSettings) Validate() error { 53 if ds.SkipValidation { 54 return nil 55 } 56 hasCreds := ds.APIKey != "" || ds.TokenSource != nil || ds.CredentialsFile != "" || ds.Credentials != nil 57 if ds.NoAuth && hasCreds { 58 return errors.New("options.WithoutAuthentication is incompatible with any option that provides credentials") 59 } 60 // Credentials should not appear with other options. 61 // We currently allow TokenSource and CredentialsFile to coexist. 62 // TODO(jba): make TokenSource & CredentialsFile an error (breaking change). 63 nCreds := 0 64 if ds.Credentials != nil { 65 nCreds++ 66 } 67 if ds.CredentialsJSON != nil { 68 nCreds++ 69 } 70 if ds.CredentialsFile != "" { 71 nCreds++ 72 } 73 if ds.APIKey != "" { 74 nCreds++ 75 } 76 if ds.TokenSource != nil { 77 nCreds++ 78 } 79 if len(ds.Scopes) > 0 && len(ds.Audiences) > 0 { 80 return errors.New("WithScopes is incompatible with WithAudience") 81 } 82 // Accept only one form of credentials, except we allow TokenSource and CredentialsFile for backwards compatibility. 83 if nCreds > 1 && !(nCreds == 2 && ds.TokenSource != nil && ds.CredentialsFile != "") { 84 return errors.New("multiple credential options provided") 85 } 86 if ds.GRPCConn != nil && ds.GRPCConnPool != nil { 87 return errors.New("WithGRPCConn is incompatible with WithConnPool") 88 } 89 if ds.HTTPClient != nil && ds.GRPCConnPool != nil { 90 return errors.New("WithHTTPClient is incompatible with WithConnPool") 91 } 92 if ds.HTTPClient != nil && ds.GRPCConn != nil { 93 return errors.New("WithHTTPClient is incompatible with WithGRPCConn") 94 } 95 if ds.HTTPClient != nil && ds.GRPCDialOpts != nil { 96 return errors.New("WithHTTPClient is incompatible with gRPC dial options") 97 } 98 if ds.HTTPClient != nil && ds.QuotaProject != "" { 99 return errors.New("WithHTTPClient is incompatible with QuotaProject") 100 } 101 if ds.HTTPClient != nil && ds.RequestReason != "" { 102 return errors.New("WithHTTPClient is incompatible with RequestReason") 103 } 104 if ds.HTTPClient != nil && ds.ClientCertSource != nil { 105 return errors.New("WithHTTPClient is incompatible with WithClientCertSource") 106 } 107 if ds.ClientCertSource != nil && (ds.GRPCConn != nil || ds.GRPCConnPool != nil || ds.GRPCConnPoolSize != 0 || ds.GRPCDialOpts != nil) { 108 return errors.New("WithClientCertSource is currently only supported for HTTP. gRPC settings are incompatible") 109 } 110 if ds.ImpersonationConfig != nil && len(ds.ImpersonationConfig.Scopes) == 0 && len(ds.Scopes) == 0 { 111 return errors.New("WithImpersonatedCredentials requires scopes being provided") 112 } 113 return nil 114} 115