1 // Copyright 2020 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 internaloption contains options used internally by Google client code.
6 package internaloption
7 8 import (
9 "context"
10 "log/slog"
11 12 "cloud.google.com/go/auth"
13 "github.com/googleapis/gax-go/v2/internallog"
14 "golang.org/x/oauth2/google"
15 "google.golang.org/api/internal"
16 "google.golang.org/api/option"
17 )
18 19 type defaultEndpointOption string
20 21 func (o defaultEndpointOption) Apply(settings *internal.DialSettings) {
22 settings.DefaultEndpoint = string(o)
23 }
24 25 // WithDefaultEndpoint is an option that indicates the default endpoint.
26 //
27 // It should only be used internally by generated clients.
28 //
29 // This is similar to WithEndpoint, but allows us to determine whether the user has overridden the default endpoint.
30 //
31 // Deprecated: WithDefaultEndpoint does not support setting the universe domain.
32 // Use WithDefaultEndpointTemplate and WithDefaultUniverseDomain to compose the
33 // default endpoint instead.
34 func WithDefaultEndpoint(url string) option.ClientOption {
35 return defaultEndpointOption(url)
36 }
37 38 type defaultEndpointTemplateOption string
39 40 func (o defaultEndpointTemplateOption) Apply(settings *internal.DialSettings) {
41 settings.DefaultEndpointTemplate = string(o)
42 }
43 44 // WithDefaultEndpointTemplate provides a template for creating the endpoint
45 // using a universe domain. See also WithDefaultUniverseDomain and
46 // option.WithUniverseDomain. The placeholder UNIVERSE_DOMAIN should be used
47 // instead of a concrete universe domain such as "googleapis.com".
48 //
49 // Example: WithDefaultEndpointTemplate("https://logging.UNIVERSE_DOMAIN/")
50 //
51 // It should only be used internally by generated clients.
52 func WithDefaultEndpointTemplate(url string) option.ClientOption {
53 return defaultEndpointTemplateOption(url)
54 }
55 56 type defaultMTLSEndpointOption string
57 58 func (o defaultMTLSEndpointOption) Apply(settings *internal.DialSettings) {
59 settings.DefaultMTLSEndpoint = string(o)
60 }
61 62 // WithDefaultMTLSEndpoint is an option that indicates the default mTLS endpoint.
63 //
64 // It should only be used internally by generated clients.
65 func WithDefaultMTLSEndpoint(url string) option.ClientOption {
66 return defaultMTLSEndpointOption(url)
67 }
68 69 // SkipDialSettingsValidation bypasses validation on ClientOptions.
70 //
71 // It should only be used internally.
72 func SkipDialSettingsValidation() option.ClientOption {
73 return skipDialSettingsValidation{}
74 }
75 76 type skipDialSettingsValidation struct{}
77 78 func (s skipDialSettingsValidation) Apply(settings *internal.DialSettings) {
79 settings.SkipValidation = true
80 }
81 82 // EnableDirectPath returns a ClientOption that overrides the default
83 // attempt to use DirectPath.
84 //
85 // It should only be used internally by generated clients.
86 // This is an EXPERIMENTAL API and may be changed or removed in the future.
87 func EnableDirectPath(dp bool) option.ClientOption {
88 return enableDirectPath(dp)
89 }
90 91 type enableDirectPath bool
92 93 func (e enableDirectPath) Apply(o *internal.DialSettings) {
94 o.EnableDirectPath = bool(e)
95 }
96 97 // EnableDirectPathXds returns a ClientOption that overrides the default
98 // DirectPath type. It is only valid when DirectPath is enabled.
99 //
100 // It should only be used internally by generated clients.
101 // This is an EXPERIMENTAL API and may be changed or removed in the future.
102 func EnableDirectPathXds() option.ClientOption {
103 return enableDirectPathXds(true)
104 }
105 106 type enableDirectPathXds bool
107 108 func (x enableDirectPathXds) Apply(o *internal.DialSettings) {
109 o.EnableDirectPathXds = bool(x)
110 }
111 112 // AllowNonDefaultServiceAccount returns a ClientOption that overrides the default
113 // requirement for using the default service account for DirectPath.
114 //
115 // It should only be used internally by generated clients.
116 // This is an EXPERIMENTAL API and may be changed or removed in the future.
117 func AllowNonDefaultServiceAccount(nd bool) option.ClientOption {
118 return allowNonDefaultServiceAccount(nd)
119 }
120 121 type allowNonDefaultServiceAccount bool
122 123 func (a allowNonDefaultServiceAccount) Apply(o *internal.DialSettings) {
124 o.AllowNonDefaultServiceAccount = bool(a)
125 }
126 127 // WithDefaultAudience returns a ClientOption that specifies a default audience
128 // to be used as the audience field ("aud") for the JWT token authentication.
129 //
130 // It should only be used internally by generated clients.
131 func WithDefaultAudience(audience string) option.ClientOption {
132 return withDefaultAudience(audience)
133 }
134 135 type withDefaultAudience string
136 137 func (w withDefaultAudience) Apply(o *internal.DialSettings) {
138 o.DefaultAudience = string(w)
139 }
140 141 // WithDefaultScopes returns a ClientOption that overrides the default OAuth2
142 // scopes to be used for a service.
143 //
144 // It should only be used internally by generated clients.
145 func WithDefaultScopes(scope ...string) option.ClientOption {
146 return withDefaultScopes(scope)
147 }
148 149 type withDefaultScopes []string
150 151 func (w withDefaultScopes) Apply(o *internal.DialSettings) {
152 o.DefaultScopes = make([]string, len(w))
153 copy(o.DefaultScopes, w)
154 }
155 156 // WithDefaultUniverseDomain returns a ClientOption that sets the default universe domain.
157 //
158 // It should only be used internally by generated clients.
159 //
160 // This is similar to the public WithUniverse, but allows us to determine whether the user has
161 // overridden the default universe.
162 func WithDefaultUniverseDomain(ud string) option.ClientOption {
163 return withDefaultUniverseDomain(ud)
164 }
165 166 type withDefaultUniverseDomain string
167 168 func (w withDefaultUniverseDomain) Apply(o *internal.DialSettings) {
169 o.DefaultUniverseDomain = string(w)
170 }
171 172 // EnableJwtWithScope returns a ClientOption that specifies if scope can be used
173 // with self-signed JWT.
174 //
175 // EnableJwtWithScope is ignored when option.WithUniverseDomain is set
176 // to a value other than the Google Default Universe (GDU) of "googleapis.com".
177 // For non-GDU domains, token exchange is impossible and services must
178 // support self-signed JWTs with scopes.
179 func EnableJwtWithScope() option.ClientOption {
180 return enableJwtWithScope(true)
181 }
182 183 type enableJwtWithScope bool
184 185 func (w enableJwtWithScope) Apply(o *internal.DialSettings) {
186 o.EnableJwtWithScope = bool(w)
187 }
188 189 // AllowHardBoundTokens returns a ClientOption that allows libraries to request a hard-bound token.
190 // Obtaining hard-bound tokens requires the connection to be established using either Application
191 // Layer Transport Security (ALTS) or mutual TLS (mTLS) with S2A. For more information on ALTS,
192 // see: https://cloud.google.com/docs/security/encryption-in-transit/application-layer-transport-security
193 //
194 // The AllowHardBoundTokens option accepts the following values (or a combination thereof):
195 //
196 // - "MTLS_S2A": Allows obtaining hard-bound tokens when the connection uses mutual TLS with S2A.
197 // - "ALTS": Allows obtaining hard-bound tokens when the connection uses ALTS.
198 //
199 // For example, to allow obtaining hard-bound tokens with either MTLS_S2A or ALTS, you would
200 // provide both values (e.g., {"MTLS_S2A","ALTS"}). If no value is provided, hard-bound tokens
201 // will not be requested.
202 //
203 // It should only be used internally by generated clients.
204 // This is an EXPERIMENTAL API and may be changed or removed in the future.
205 func AllowHardBoundTokens(protocol ...string) option.ClientOption {
206 return allowHardBoundTokens(protocol)
207 }
208 209 type allowHardBoundTokens []string
210 211 func (a allowHardBoundTokens) Apply(o *internal.DialSettings) {
212 o.AllowHardBoundTokens = make([]string, len(a))
213 copy(o.AllowHardBoundTokens, a)
214 }
215 216 // WithCredentials returns a client option to specify credentials which will be used to authenticate API calls.
217 // This credential takes precedence over all other credential options.
218 func WithCredentials(creds *google.Credentials) option.ClientOption {
219 return (*withCreds)(creds)
220 }
221 222 type withCreds google.Credentials
223 224 func (w *withCreds) Apply(o *internal.DialSettings) {
225 o.InternalCredentials = (*google.Credentials)(w)
226 }
227 228 // EnableNewAuthLibrary returns a ClientOption that specifies if libraries in this
229 // module to delegate auth to our new library. This option will be removed in
230 // the future once all clients have been moved to the new auth layer.
231 func EnableNewAuthLibrary() option.ClientOption {
232 return enableNewAuthLibrary(true)
233 }
234 235 type enableNewAuthLibrary bool
236 237 func (w enableNewAuthLibrary) Apply(o *internal.DialSettings) {
238 o.EnableNewAuthLibrary = bool(w)
239 }
240 241 // EnableAsyncRefreshDryRun returns a ClientOption that specifies if libraries in this
242 // module should asynchronously refresh auth token in parallel to sync refresh.
243 //
244 // This option can be used to determine whether refreshing the token asymnchronously
245 // prior to its actual expiry works without any issues in a particular environment.
246 //
247 // errHandler function will be called when there is an error while refreshing
248 // the token asynchronously.
249 //
250 // This is an EXPERIMENTAL option and will be removed in the future.
251 // TODO(b/372244283): Remove after b/358175516 has been fixed
252 func EnableAsyncRefreshDryRun(errHandler func()) option.ClientOption {
253 return enableAsyncRefreshDryRun{
254 errHandler: errHandler,
255 }
256 }
257 258 // TODO(b/372244283): Remove after b/358175516 has been fixed
259 type enableAsyncRefreshDryRun struct {
260 errHandler func()
261 }
262 263 // TODO(b/372244283): Remove after b/358175516 has been fixed
264 func (w enableAsyncRefreshDryRun) Apply(o *internal.DialSettings) {
265 o.EnableAsyncRefreshDryRun = w.errHandler
266 }
267 268 // EmbeddableAdapter is a no-op option.ClientOption that allow libraries to
269 // create their own client options by embedding this type into their own
270 // client-specific option wrapper. See example for usage.
271 type EmbeddableAdapter struct{}
272 273 func (*EmbeddableAdapter) Apply(_ *internal.DialSettings) {}
274 275 // GetLogger is a helper for client libraries to extract the [slog.Logger] from
276 // the provided options or return a default logger if one is not found.
277 //
278 // It should only be used internally by generated clients. This is an EXPERIMENTAL API
279 // and may be changed or removed in the future.
280 func GetLogger(opts []option.ClientOption) *slog.Logger {
281 var ds internal.DialSettings
282 for _, opt := range opts {
283 opt.Apply(&ds)
284 }
285 return internallog.New(ds.Logger)
286 }
287 288 // AuthCreds returns [cloud.google.com/go/auth.Credentials] using the following
289 // options provided via [option.ClientOption], including legacy oauth2/google
290 // options, in this order:
291 //
292 // - [option.WithoutAuthentication]
293 // - [option.Credentials]
294 // - [WithCredentials] (internal use only)
295 // - [option.WithCredentials]
296 // - [option.WithTokenSource]
297 //
298 // If there are no applicable credentials options, then it passes the
299 // following options to [cloud.google.com/go/auth/credentials.DetectDefault] and
300 // returns the result:
301 //
302 // - [option.WithAudiences]
303 // - [option.WithAuthCredentialsFile]
304 // - [option.WithCredentialsFile]
305 // - [option.WithAuthCredentialsJSON]
306 // - [option.WithCredentialsJSON]
307 // - [option.WithScopes]
308 // - [WithDefaultScopes] (internal use only)
309 // - [EnableJwtWithScope] (internal use only)
310 //
311 // This function should only be used internally by generated clients. This is an
312 // EXPERIMENTAL API and may be changed or removed in the future.
313 func AuthCreds(ctx context.Context, opts []option.ClientOption) (*auth.Credentials, error) {
314 var ds internal.DialSettings
315 for _, opt := range opts {
316 opt.Apply(&ds)
317 }
318 return internal.AuthCreds(ctx, &ds)
319 }
320