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 DefaultScopes []string 27 EnableJwtWithScope bool 28 TokenSource oauth2.TokenSource 29 Credentials *google.Credentials 30 CredentialsFile string // if set, Token Source is ignored. 31 CredentialsJSON []byte 32 UserAgent string 33 APIKey string 34 Audiences []string 35 DefaultAudience string 36 HTTPClient *http.Client 37 GRPCDialOpts []grpc.DialOption 38 GRPCConn *grpc.ClientConn 39 GRPCConnPool ConnPool 40 GRPCConnPoolSize int 41 NoAuth bool 42 TelemetryDisabled bool 43 ClientCertSource func(*tls.CertificateRequestInfo) (*tls.Certificate, error) 44 CustomClaims map[string]interface{} 45 SkipValidation bool 46 ImpersonationConfig *impersonate.Config 47 EnableDirectPath bool 48 49 // Google API system parameters. For more information please read: 50 // https://cloud.google.com/apis/docs/system-parameters 51 QuotaProject string 52 RequestReason string 53} 54 55// GetScopes returns the user-provided scopes, if set, or else falls back to the 56// default scopes. 57func (ds *DialSettings) GetScopes() []string { 58 if len(ds.Scopes) > 0 { 59 return ds.Scopes 60 } 61 return ds.DefaultScopes 62} 63 64// GetAudience returns the user-provided audience, if set, or else falls back to the default audience. 65func (ds *DialSettings) GetAudience() string { 66 if ds.HasCustomAudience() { 67 return ds.Audiences[0] 68 } 69 return ds.DefaultAudience 70} 71 72// HasCustomAudience returns true if a custom audience is provided by users. 73func (ds *DialSettings) HasCustomAudience() bool { 74 return len(ds.Audiences) > 0 75} 76 77// Validate reports an error if ds is invalid. 78func (ds *DialSettings) Validate() error { 79 if ds.SkipValidation { 80 return nil 81 } 82 hasCreds := ds.APIKey != "" || ds.TokenSource != nil || ds.CredentialsFile != "" || ds.Credentials != nil 83 if ds.NoAuth && hasCreds { 84 return errors.New("options.WithoutAuthentication is incompatible with any option that provides credentials") 85 } 86 // Credentials should not appear with other options. 87 // We currently allow TokenSource and CredentialsFile to coexist. 88 // TODO(jba): make TokenSource & CredentialsFile an error (breaking change). 89 nCreds := 0 90 if ds.Credentials != nil { 91 nCreds++ 92 } 93 if ds.CredentialsJSON != nil { 94 nCreds++ 95 } 96 if ds.CredentialsFile != "" { 97 nCreds++ 98 } 99 if ds.APIKey != "" { 100 nCreds++ 101 } 102 if ds.TokenSource != nil { 103 nCreds++ 104 } 105 if len(ds.Scopes) > 0 && len(ds.Audiences) > 0 { 106 return errors.New("WithScopes is incompatible with WithAudience") 107 } 108 // Accept only one form of credentials, except we allow TokenSource and CredentialsFile for backwards compatibility. 109 if nCreds > 1 && !(nCreds == 2 && ds.TokenSource != nil && ds.CredentialsFile != "") { 110 return errors.New("multiple credential options provided") 111 } 112 if ds.GRPCConn != nil && ds.GRPCConnPool != nil { 113 return errors.New("WithGRPCConn is incompatible with WithConnPool") 114 } 115 if ds.HTTPClient != nil && ds.GRPCConnPool != nil { 116 return errors.New("WithHTTPClient is incompatible with WithConnPool") 117 } 118 if ds.HTTPClient != nil && ds.GRPCConn != nil { 119 return errors.New("WithHTTPClient is incompatible with WithGRPCConn") 120 } 121 if ds.HTTPClient != nil && ds.GRPCDialOpts != nil { 122 return errors.New("WithHTTPClient is incompatible with gRPC dial options") 123 } 124 if ds.HTTPClient != nil && ds.QuotaProject != "" { 125 return errors.New("WithHTTPClient is incompatible with QuotaProject") 126 } 127 if ds.HTTPClient != nil && ds.RequestReason != "" { 128 return errors.New("WithHTTPClient is incompatible with RequestReason") 129 } 130 if ds.HTTPClient != nil && ds.ClientCertSource != nil { 131 return errors.New("WithHTTPClient is incompatible with WithClientCertSource") 132 } 133 if ds.ClientCertSource != nil && (ds.GRPCConn != nil || ds.GRPCConnPool != nil || ds.GRPCConnPoolSize != 0 || ds.GRPCDialOpts != nil) { 134 return errors.New("WithClientCertSource is currently only supported for HTTP. gRPC settings are incompatible") 135 } 136 if ds.ImpersonationConfig != nil && len(ds.ImpersonationConfig.Scopes) == 0 && len(ds.Scopes) == 0 { 137 return errors.New("WithImpersonatedCredentials requires scopes being provided") 138 } 139 return nil 140} 141