...
1
2
3
4
5
6 package internal
7
8 import (
9 "crypto/tls"
10 "errors"
11 "net/http"
12 "os"
13 "strconv"
14 "time"
15
16 "cloud.google.com/go/auth"
17 "golang.org/x/oauth2"
18 "golang.org/x/oauth2/google"
19 "google.golang.org/api/internal/impersonate"
20 "google.golang.org/grpc"
21 )
22
23 const (
24 newAuthLibEnvVar = "GOOGLE_API_GO_EXPERIMENTAL_ENABLE_NEW_AUTH_LIB"
25 newAuthLibDisabledEnVar = "GOOGLE_API_GO_EXPERIMENTAL_DISABLE_NEW_AUTH_LIB"
26 universeDomainEnvVar = "GOOGLE_CLOUD_UNIVERSE_DOMAIN"
27 defaultUniverseDomain = "googleapis.com"
28 )
29
30
31
32 type DialSettings struct {
33 Endpoint string
34 DefaultEndpoint string
35 DefaultEndpointTemplate string
36 DefaultMTLSEndpoint string
37 Scopes []string
38 DefaultScopes []string
39 EnableJwtWithScope bool
40 TokenSource oauth2.TokenSource
41 Credentials *google.Credentials
42 CredentialsFile string
43 CredentialsJSON []byte
44 InternalCredentials *google.Credentials
45 UserAgent string
46 APIKey string
47 Audiences []string
48 DefaultAudience string
49 HTTPClient *http.Client
50 GRPCDialOpts []grpc.DialOption
51 GRPCConn *grpc.ClientConn
52 GRPCConnPool ConnPool
53 GRPCConnPoolSize int
54 NoAuth bool
55 TelemetryDisabled bool
56 ClientCertSource func(*tls.CertificateRequestInfo) (*tls.Certificate, error)
57 CustomClaims map[string]interface{}
58 SkipValidation bool
59 ImpersonationConfig *impersonate.Config
60 EnableDirectPath bool
61 EnableDirectPathXds bool
62 AllowNonDefaultServiceAccount bool
63 DefaultUniverseDomain string
64 UniverseDomain string
65
66
67 QuotaProject string
68 RequestReason string
69
70
71 AuthCredentials *auth.Credentials
72 EnableNewAuthLibrary bool
73 }
74
75
76
77 func (ds *DialSettings) GetScopes() []string {
78 if len(ds.Scopes) > 0 {
79 return ds.Scopes
80 }
81 return ds.DefaultScopes
82 }
83
84
85 func (ds *DialSettings) GetAudience() string {
86 if ds.HasCustomAudience() {
87 return ds.Audiences[0]
88 }
89 return ds.DefaultAudience
90 }
91
92
93 func (ds *DialSettings) HasCustomAudience() bool {
94 return len(ds.Audiences) > 0
95 }
96
97
98 func (ds *DialSettings) IsNewAuthLibraryEnabled() bool {
99
100
101 if b, err := strconv.ParseBool(os.Getenv(newAuthLibDisabledEnVar)); err == nil && b {
102 return false
103 }
104 if ds.EnableNewAuthLibrary {
105 return true
106 }
107 if b, err := strconv.ParseBool(os.Getenv(newAuthLibEnvVar)); err == nil {
108 return b
109 }
110 return false
111 }
112
113
114 func (ds *DialSettings) Validate() error {
115 if ds.SkipValidation {
116 return nil
117 }
118 hasCreds := ds.APIKey != "" || ds.TokenSource != nil || ds.CredentialsFile != "" || ds.Credentials != nil
119 if ds.NoAuth && hasCreds {
120 return errors.New("options.WithoutAuthentication is incompatible with any option that provides credentials")
121 }
122
123
124
125 nCreds := 0
126 if ds.Credentials != nil {
127 nCreds++
128 }
129 if ds.CredentialsJSON != nil {
130 nCreds++
131 }
132 if ds.CredentialsFile != "" {
133 nCreds++
134 }
135 if ds.APIKey != "" {
136 nCreds++
137 }
138 if ds.TokenSource != nil {
139 nCreds++
140 }
141 if len(ds.Scopes) > 0 && len(ds.Audiences) > 0 {
142 return errors.New("WithScopes is incompatible with WithAudience")
143 }
144
145 if nCreds > 1 && !(nCreds == 2 && ds.TokenSource != nil && ds.CredentialsFile != "") {
146 return errors.New("multiple credential options provided")
147 }
148 if ds.GRPCConn != nil && ds.GRPCConnPool != nil {
149 return errors.New("WithGRPCConn is incompatible with WithConnPool")
150 }
151 if ds.HTTPClient != nil && ds.GRPCConnPool != nil {
152 return errors.New("WithHTTPClient is incompatible with WithConnPool")
153 }
154 if ds.HTTPClient != nil && ds.GRPCConn != nil {
155 return errors.New("WithHTTPClient is incompatible with WithGRPCConn")
156 }
157 if ds.HTTPClient != nil && ds.GRPCDialOpts != nil {
158 return errors.New("WithHTTPClient is incompatible with gRPC dial options")
159 }
160 if ds.HTTPClient != nil && ds.QuotaProject != "" {
161 return errors.New("WithHTTPClient is incompatible with QuotaProject")
162 }
163 if ds.HTTPClient != nil && ds.RequestReason != "" {
164 return errors.New("WithHTTPClient is incompatible with RequestReason")
165 }
166 if ds.HTTPClient != nil && ds.ClientCertSource != nil {
167 return errors.New("WithHTTPClient is incompatible with WithClientCertSource")
168 }
169 if ds.ClientCertSource != nil && (ds.GRPCConn != nil || ds.GRPCConnPool != nil || ds.GRPCConnPoolSize != 0 || ds.GRPCDialOpts != nil) {
170 return errors.New("WithClientCertSource is currently only supported for HTTP. gRPC settings are incompatible")
171 }
172 if ds.ImpersonationConfig != nil && len(ds.ImpersonationConfig.Scopes) == 0 && len(ds.Scopes) == 0 {
173 return errors.New("WithImpersonatedCredentials requires scopes being provided")
174 }
175 return nil
176 }
177
178
179
180 func (ds *DialSettings) GetDefaultUniverseDomain() string {
181 return defaultUniverseDomain
182 }
183
184
185
186
187
188
189
190 func (ds *DialSettings) GetUniverseDomain() string {
191 if ds.UniverseDomain != "" {
192 return ds.UniverseDomain
193 }
194 if envUD := os.Getenv(universeDomainEnvVar); envUD != "" {
195 return envUD
196 }
197 return defaultUniverseDomain
198 }
199
200
201
202 func (ds *DialSettings) IsUniverseDomainGDU() bool {
203 return ds.GetUniverseDomain() == defaultUniverseDomain
204 }
205
206
207
208
209
210 func GetUniverseDomain(creds *google.Credentials) (string, error) {
211 timer := time.NewTimer(time.Second)
212 defer timer.Stop()
213 errors := make(chan error)
214 results := make(chan string)
215
216 go func() {
217 result, err := creds.GetUniverseDomain()
218 if err != nil {
219 errors <- err
220 return
221 }
222 results <- result
223 }()
224
225 select {
226 case <-errors:
227
228
229 return defaultUniverseDomain, nil
230 case res := <-results:
231 return res, nil
232 case <-timer.C:
233
234
235
236
237
238
239
240
241 return defaultUniverseDomain, nil
242 }
243 }
244
View as plain text