internaloption.go raw

   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