]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blame - vendor/github.com/aws/aws-sdk-go/aws/session/session.go
update vendor and go.mod
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / aws / aws-sdk-go / aws / session / session.go
CommitLineData
bae9f6d2
JC
1package session
2
3import (
4 "crypto/tls"
5 "crypto/x509"
6 "fmt"
7 "io"
8 "io/ioutil"
9 "net/http"
10 "os"
863486a6 11 "time"
bae9f6d2
JC
12
13 "github.com/aws/aws-sdk-go/aws"
14 "github.com/aws/aws-sdk-go/aws/awserr"
15 "github.com/aws/aws-sdk-go/aws/client"
16 "github.com/aws/aws-sdk-go/aws/corehandlers"
17 "github.com/aws/aws-sdk-go/aws/credentials"
15c0b25d 18 "github.com/aws/aws-sdk-go/aws/csm"
bae9f6d2
JC
19 "github.com/aws/aws-sdk-go/aws/defaults"
20 "github.com/aws/aws-sdk-go/aws/endpoints"
21 "github.com/aws/aws-sdk-go/aws/request"
22)
23
107c1cdb
ND
24const (
25 // ErrCodeSharedConfig represents an error that occurs in the shared
26 // configuration logic
27 ErrCodeSharedConfig = "SharedConfigErr"
28)
29
30// ErrSharedConfigSourceCollision will be returned if a section contains both
31// source_profile and credential_source
32var ErrSharedConfigSourceCollision = awserr.New(ErrCodeSharedConfig, "only source profile or credential source can be specified, not both", nil)
33
34// ErrSharedConfigECSContainerEnvVarEmpty will be returned if the environment
35// variables are empty and Environment was set as the credential source
36var ErrSharedConfigECSContainerEnvVarEmpty = awserr.New(ErrCodeSharedConfig, "EcsContainer was specified as the credential_source, but 'AWS_CONTAINER_CREDENTIALS_RELATIVE_URI' was not set", nil)
37
38// ErrSharedConfigInvalidCredSource will be returned if an invalid credential source was provided
39var ErrSharedConfigInvalidCredSource = awserr.New(ErrCodeSharedConfig, "credential source values must be EcsContainer, Ec2InstanceMetadata, or Environment", nil)
40
bae9f6d2
JC
41// A Session provides a central location to create service clients from and
42// store configurations and request handlers for those services.
43//
44// Sessions are safe to create service clients concurrently, but it is not safe
45// to mutate the Session concurrently.
46//
15c0b25d 47// The Session satisfies the service client's client.ConfigProvider.
bae9f6d2
JC
48type Session struct {
49 Config *aws.Config
50 Handlers request.Handlers
51}
52
53// New creates a new instance of the handlers merging in the provided configs
54// on top of the SDK's default configurations. Once the Session is created it
55// can be mutated to modify the Config or Handlers. The Session is safe to be
56// read concurrently, but it should not be written to concurrently.
57//
58// If the AWS_SDK_LOAD_CONFIG environment is set to a truthy value, the New
59// method could now encounter an error when loading the configuration. When
60// The environment variable is set, and an error occurs, New will return a
61// session that will fail all requests reporting the error that occurred while
62// loading the session. Use NewSession to get the error when creating the
63// session.
64//
65// If the AWS_SDK_LOAD_CONFIG environment variable is set to a truthy value
66// the shared config file (~/.aws/config) will also be loaded, in addition to
67// the shared credentials file (~/.aws/credentials). Values set in both the
68// shared config, and shared credentials will be taken from the shared
69// credentials file.
70//
71// Deprecated: Use NewSession functions to create sessions instead. NewSession
72// has the same functionality as New except an error can be returned when the
73// func is called instead of waiting to receive an error until a request is made.
74func New(cfgs ...*aws.Config) *Session {
75 // load initial config from environment
76 envCfg := loadEnvConfig()
77
78 if envCfg.EnableSharedConfig {
15c0b25d
AP
79 var cfg aws.Config
80 cfg.MergeIn(cfgs...)
81 s, err := NewSessionWithOptions(Options{
82 Config: cfg,
83 SharedConfigState: SharedConfigEnable,
84 })
bae9f6d2
JC
85 if err != nil {
86 // Old session.New expected all errors to be discovered when
87 // a request is made, and would report the errors then. This
88 // needs to be replicated if an error occurs while creating
89 // the session.
90 msg := "failed to create session with AWS_SDK_LOAD_CONFIG enabled. " +
91 "Use session.NewSession to handle errors occurring during session creation."
92
93 // Session creation failed, need to report the error and prevent
94 // any requests from succeeding.
95 s = &Session{Config: defaults.Config()}
96 s.Config.MergeIn(cfgs...)
97 s.Config.Logger.Log("ERROR:", msg, "Error:", err)
98 s.Handlers.Validate.PushBack(func(r *request.Request) {
99 r.Error = err
100 })
101 }
15c0b25d 102
bae9f6d2
JC
103 return s
104 }
105
15c0b25d
AP
106 s := deprecatedNewSession(cfgs...)
107 if envCfg.CSMEnabled {
863486a6
AG
108 err := enableCSM(&s.Handlers, envCfg.CSMClientID,
109 envCfg.CSMHost, envCfg.CSMPort, s.Config.Logger)
110 if err != nil {
111 err = fmt.Errorf("failed to enable CSM, %v", err)
112 s.Config.Logger.Log("ERROR:", err.Error())
113 s.Handlers.Validate.PushBack(func(r *request.Request) {
114 r.Error = err
115 })
116 }
15c0b25d
AP
117 }
118
119 return s
bae9f6d2
JC
120}
121
122// NewSession returns a new Session created from SDK defaults, config files,
123// environment, and user provided config files. Once the Session is created
124// it can be mutated to modify the Config or Handlers. The Session is safe to
125// be read concurrently, but it should not be written to concurrently.
126//
127// If the AWS_SDK_LOAD_CONFIG environment variable is set to a truthy value
128// the shared config file (~/.aws/config) will also be loaded in addition to
129// the shared credentials file (~/.aws/credentials). Values set in both the
130// shared config, and shared credentials will be taken from the shared
131// credentials file. Enabling the Shared Config will also allow the Session
132// to be built with retrieving credentials with AssumeRole set in the config.
133//
134// See the NewSessionWithOptions func for information on how to override or
135// control through code how the Session will be created. Such as specifying the
136// config profile, and controlling if shared config is enabled or not.
137func NewSession(cfgs ...*aws.Config) (*Session, error) {
138 opts := Options{}
139 opts.Config.MergeIn(cfgs...)
140
141 return NewSessionWithOptions(opts)
142}
143
144// SharedConfigState provides the ability to optionally override the state
145// of the session's creation based on the shared config being enabled or
146// disabled.
147type SharedConfigState int
148
149const (
150 // SharedConfigStateFromEnv does not override any state of the
151 // AWS_SDK_LOAD_CONFIG env var. It is the default value of the
152 // SharedConfigState type.
153 SharedConfigStateFromEnv SharedConfigState = iota
154
155 // SharedConfigDisable overrides the AWS_SDK_LOAD_CONFIG env var value
156 // and disables the shared config functionality.
157 SharedConfigDisable
158
159 // SharedConfigEnable overrides the AWS_SDK_LOAD_CONFIG env var value
160 // and enables the shared config functionality.
161 SharedConfigEnable
162)
163
164// Options provides the means to control how a Session is created and what
165// configuration values will be loaded.
166//
167type Options struct {
168 // Provides config values for the SDK to use when creating service clients
169 // and making API requests to services. Any value set in with this field
170 // will override the associated value provided by the SDK defaults,
171 // environment or config files where relevant.
172 //
173 // If not set, configuration values from from SDK defaults, environment,
174 // config will be used.
175 Config aws.Config
176
177 // Overrides the config profile the Session should be created from. If not
178 // set the value of the environment variable will be loaded (AWS_PROFILE,
179 // or AWS_DEFAULT_PROFILE if the Shared Config is enabled).
180 //
181 // If not set and environment variables are not set the "default"
182 // (DefaultSharedConfigProfile) will be used as the profile to load the
183 // session config from.
184 Profile string
185
186 // Instructs how the Session will be created based on the AWS_SDK_LOAD_CONFIG
187 // environment variable. By default a Session will be created using the
188 // value provided by the AWS_SDK_LOAD_CONFIG environment variable.
189 //
190 // Setting this value to SharedConfigEnable or SharedConfigDisable
191 // will allow you to override the AWS_SDK_LOAD_CONFIG environment variable
192 // and enable or disable the shared config functionality.
193 SharedConfigState SharedConfigState
194
9b12e4fe
JC
195 // Ordered list of files the session will load configuration from.
196 // It will override environment variable AWS_SHARED_CREDENTIALS_FILE, AWS_CONFIG_FILE.
197 SharedConfigFiles []string
198
bae9f6d2
JC
199 // When the SDK's shared config is configured to assume a role with MFA
200 // this option is required in order to provide the mechanism that will
201 // retrieve the MFA token. There is no default value for this field. If
202 // it is not set an error will be returned when creating the session.
203 //
204 // This token provider will be called when ever the assumed role's
205 // credentials need to be refreshed. Within the context of service clients
206 // all sharing the same session the SDK will ensure calls to the token
207 // provider are atomic. When sharing a token provider across multiple
208 // sessions additional synchronization logic is needed to ensure the
209 // token providers do not introduce race conditions. It is recommend to
210 // share the session where possible.
211 //
212 // stscreds.StdinTokenProvider is a basic implementation that will prompt
213 // from stdin for the MFA token code.
214 //
215 // This field is only used if the shared configuration is enabled, and
216 // the config enables assume role wit MFA via the mfa_serial field.
217 AssumeRoleTokenProvider func() (string, error)
218
863486a6
AG
219 // When the SDK's shared config is configured to assume a role this option
220 // may be provided to set the expiry duration of the STS credentials.
221 // Defaults to 15 minutes if not set as documented in the
222 // stscreds.AssumeRoleProvider.
223 AssumeRoleDuration time.Duration
224
bae9f6d2
JC
225 // Reader for a custom Credentials Authority (CA) bundle in PEM format that
226 // the SDK will use instead of the default system's root CA bundle. Use this
227 // only if you want to replace the CA bundle the SDK uses for TLS requests.
228 //
229 // Enabling this option will attempt to merge the Transport into the SDK's HTTP
230 // client. If the client's Transport is not a http.Transport an error will be
231 // returned. If the Transport's TLS config is set this option will cause the SDK
232 // to overwrite the Transport's TLS config's RootCAs value. If the CA
233 // bundle reader contains multiple certificates all of them will be loaded.
234 //
235 // The Session option CustomCABundle is also available when creating sessions
236 // to also enable this feature. CustomCABundle session option field has priority
237 // over the AWS_CA_BUNDLE environment variable, and will be used if both are set.
238 CustomCABundle io.Reader
863486a6
AG
239
240 // The handlers that the session and all API clients will be created with.
241 // This must be a complete set of handlers. Use the defaults.Handlers()
242 // function to initialize this value before changing the handlers to be
243 // used by the SDK.
244 Handlers request.Handlers
bae9f6d2
JC
245}
246
247// NewSessionWithOptions returns a new Session created from SDK defaults, config files,
248// environment, and user provided config files. This func uses the Options
249// values to configure how the Session is created.
250//
251// If the AWS_SDK_LOAD_CONFIG environment variable is set to a truthy value
252// the shared config file (~/.aws/config) will also be loaded in addition to
253// the shared credentials file (~/.aws/credentials). Values set in both the
254// shared config, and shared credentials will be taken from the shared
255// credentials file. Enabling the Shared Config will also allow the Session
256// to be built with retrieving credentials with AssumeRole set in the config.
257//
258// // Equivalent to session.New
259// sess := session.Must(session.NewSessionWithOptions(session.Options{}))
260//
261// // Specify profile to load for the session's config
262// sess := session.Must(session.NewSessionWithOptions(session.Options{
263// Profile: "profile_name",
264// }))
265//
266// // Specify profile for config and region for requests
267// sess := session.Must(session.NewSessionWithOptions(session.Options{
268// Config: aws.Config{Region: aws.String("us-east-1")},
269// Profile: "profile_name",
270// }))
271//
272// // Force enable Shared Config support
273// sess := session.Must(session.NewSessionWithOptions(session.Options{
274// SharedConfigState: session.SharedConfigEnable,
275// }))
276func NewSessionWithOptions(opts Options) (*Session, error) {
277 var envCfg envConfig
278 if opts.SharedConfigState == SharedConfigEnable {
279 envCfg = loadSharedEnvConfig()
280 } else {
281 envCfg = loadEnvConfig()
282 }
283
284 if len(opts.Profile) > 0 {
285 envCfg.Profile = opts.Profile
286 }
287
288 switch opts.SharedConfigState {
289 case SharedConfigDisable:
290 envCfg.EnableSharedConfig = false
291 case SharedConfigEnable:
292 envCfg.EnableSharedConfig = true
293 }
294
295 // Only use AWS_CA_BUNDLE if session option is not provided.
296 if len(envCfg.CustomCABundle) != 0 && opts.CustomCABundle == nil {
297 f, err := os.Open(envCfg.CustomCABundle)
298 if err != nil {
299 return nil, awserr.New("LoadCustomCABundleError",
300 "failed to open custom CA bundle PEM file", err)
301 }
302 defer f.Close()
303 opts.CustomCABundle = f
304 }
305
306 return newSession(opts, envCfg, &opts.Config)
307}
308
309// Must is a helper function to ensure the Session is valid and there was no
310// error when calling a NewSession function.
311//
312// This helper is intended to be used in variable initialization to load the
313// Session and configuration at startup. Such as:
314//
315// var sess = session.Must(session.NewSession())
316func Must(sess *Session, err error) *Session {
317 if err != nil {
318 panic(err)
319 }
320
321 return sess
322}
323
324func deprecatedNewSession(cfgs ...*aws.Config) *Session {
325 cfg := defaults.Config()
326 handlers := defaults.Handlers()
327
328 // Apply the passed in configs so the configuration can be applied to the
329 // default credential chain
330 cfg.MergeIn(cfgs...)
331 if cfg.EndpointResolver == nil {
332 // An endpoint resolver is required for a session to be able to provide
333 // endpoints for service client configurations.
334 cfg.EndpointResolver = endpoints.DefaultResolver()
335 }
336 cfg.Credentials = defaults.CredChain(cfg, handlers)
337
338 // Reapply any passed in configs to override credentials if set
339 cfg.MergeIn(cfgs...)
340
341 s := &Session{
342 Config: cfg,
343 Handlers: handlers,
344 }
345
346 initHandlers(s)
bae9f6d2
JC
347 return s
348}
349
863486a6
AG
350func enableCSM(handlers *request.Handlers,
351 clientID, host, port string,
352 logger aws.Logger,
353) error {
354 if logger != nil {
355 logger.Log("Enabling CSM")
15c0b25d
AP
356 }
357
863486a6 358 r, err := csm.Start(clientID, csm.AddressWithDefaults(host, port))
15c0b25d 359 if err != nil {
863486a6 360 return err
15c0b25d
AP
361 }
362 r.InjectHandlers(handlers)
863486a6
AG
363
364 return nil
15c0b25d
AP
365}
366
bae9f6d2
JC
367func newSession(opts Options, envCfg envConfig, cfgs ...*aws.Config) (*Session, error) {
368 cfg := defaults.Config()
863486a6
AG
369
370 handlers := opts.Handlers
371 if handlers.IsEmpty() {
372 handlers = defaults.Handlers()
373 }
bae9f6d2
JC
374
375 // Get a merged version of the user provided config to determine if
376 // credentials were.
377 userCfg := &aws.Config{}
378 userCfg.MergeIn(cfgs...)
863486a6 379 cfg.MergeIn(userCfg)
bae9f6d2 380
9b12e4fe 381 // Ordered config files will be loaded in with later files overwriting
bae9f6d2 382 // previous config file values.
9b12e4fe
JC
383 var cfgFiles []string
384 if opts.SharedConfigFiles != nil {
385 cfgFiles = opts.SharedConfigFiles
386 } else {
387 cfgFiles = []string{envCfg.SharedConfigFile, envCfg.SharedCredentialsFile}
388 if !envCfg.EnableSharedConfig {
389 // The shared config file (~/.aws/config) is only loaded if instructed
390 // to load via the envConfig.EnableSharedConfig (AWS_SDK_LOAD_CONFIG).
391 cfgFiles = cfgFiles[1:]
392 }
bae9f6d2
JC
393 }
394
395 // Load additional config from file(s)
863486a6 396 sharedCfg, err := loadSharedConfig(envCfg.Profile, cfgFiles, envCfg.EnableSharedConfig)
bae9f6d2 397 if err != nil {
863486a6
AG
398 if _, ok := err.(SharedConfigProfileNotExistsError); !ok {
399 return nil, err
400 }
bae9f6d2
JC
401 }
402
403 if err := mergeConfigSrcs(cfg, userCfg, envCfg, sharedCfg, handlers, opts); err != nil {
404 return nil, err
405 }
406
407 s := &Session{
408 Config: cfg,
409 Handlers: handlers,
410 }
411
412 initHandlers(s)
15c0b25d 413 if envCfg.CSMEnabled {
863486a6
AG
414 err := enableCSM(&s.Handlers, envCfg.CSMClientID,
415 envCfg.CSMHost, envCfg.CSMPort, s.Config.Logger)
416 if err != nil {
417 return nil, err
418 }
15c0b25d 419 }
bae9f6d2
JC
420
421 // Setup HTTP client with custom cert bundle if enabled
422 if opts.CustomCABundle != nil {
423 if err := loadCustomCABundle(s, opts.CustomCABundle); err != nil {
424 return nil, err
425 }
426 }
427
428 return s, nil
429}
430
431func loadCustomCABundle(s *Session, bundle io.Reader) error {
432 var t *http.Transport
433 switch v := s.Config.HTTPClient.Transport.(type) {
434 case *http.Transport:
435 t = v
436 default:
437 if s.Config.HTTPClient.Transport != nil {
438 return awserr.New("LoadCustomCABundleError",
439 "unable to load custom CA bundle, HTTPClient's transport unsupported type", nil)
440 }
441 }
442 if t == nil {
107c1cdb
ND
443 // Nil transport implies `http.DefaultTransport` should be used. Since
444 // the SDK cannot modify, nor copy the `DefaultTransport` specifying
445 // the values the next closest behavior.
446 t = getCABundleTransport()
bae9f6d2
JC
447 }
448
449 p, err := loadCertPool(bundle)
450 if err != nil {
451 return err
452 }
453 if t.TLSClientConfig == nil {
454 t.TLSClientConfig = &tls.Config{}
455 }
456 t.TLSClientConfig.RootCAs = p
457
458 s.Config.HTTPClient.Transport = t
459
460 return nil
461}
462
463func loadCertPool(r io.Reader) (*x509.CertPool, error) {
464 b, err := ioutil.ReadAll(r)
465 if err != nil {
466 return nil, awserr.New("LoadCustomCABundleError",
467 "failed to read custom CA bundle PEM file", err)
468 }
469
470 p := x509.NewCertPool()
471 if !p.AppendCertsFromPEM(b) {
472 return nil, awserr.New("LoadCustomCABundleError",
473 "failed to load custom CA bundle PEM file", err)
474 }
475
476 return p, nil
477}
478
863486a6
AG
479func mergeConfigSrcs(cfg, userCfg *aws.Config,
480 envCfg envConfig, sharedCfg sharedConfig,
481 handlers request.Handlers,
482 sessOpts Options,
483) error {
bae9f6d2
JC
484
485 // Region if not already set by user
486 if len(aws.StringValue(cfg.Region)) == 0 {
487 if len(envCfg.Region) > 0 {
488 cfg.WithRegion(envCfg.Region)
489 } else if envCfg.EnableSharedConfig && len(sharedCfg.Region) > 0 {
490 cfg.WithRegion(sharedCfg.Region)
491 }
492 }
493
107c1cdb
ND
494 if cfg.EnableEndpointDiscovery == nil {
495 if envCfg.EnableEndpointDiscovery != nil {
496 cfg.WithEndpointDiscovery(*envCfg.EnableEndpointDiscovery)
497 } else if envCfg.EnableSharedConfig && sharedCfg.EnableEndpointDiscovery != nil {
498 cfg.WithEndpointDiscovery(*sharedCfg.EnableEndpointDiscovery)
499 }
500 }
501
863486a6
AG
502 // Configure credentials if not already set by the user when creating the
503 // Session.
bae9f6d2 504 if cfg.Credentials == credentials.AnonymousCredentials && userCfg.Credentials == nil {
863486a6
AG
505 creds, err := resolveCredentials(cfg, envCfg, sharedCfg, handlers, sessOpts)
506 if err != nil {
507 return err
bae9f6d2 508 }
863486a6 509 cfg.Credentials = creds
bae9f6d2
JC
510 }
511
512 return nil
513}
514
bae9f6d2
JC
515func initHandlers(s *Session) {
516 // Add the Validate parameter handler if it is not disabled.
517 s.Handlers.Validate.Remove(corehandlers.ValidateParametersHandler)
518 if !aws.BoolValue(s.Config.DisableParamValidation) {
519 s.Handlers.Validate.PushBackNamed(corehandlers.ValidateParametersHandler)
520 }
521}
522
523// Copy creates and returns a copy of the current Session, coping the config
524// and handlers. If any additional configs are provided they will be merged
525// on top of the Session's copied config.
526//
527// // Create a copy of the current Session, configured for the us-west-2 region.
528// sess.Copy(&aws.Config{Region: aws.String("us-west-2")})
529func (s *Session) Copy(cfgs ...*aws.Config) *Session {
530 newSession := &Session{
531 Config: s.Config.Copy(cfgs...),
532 Handlers: s.Handlers.Copy(),
533 }
534
535 initHandlers(newSession)
536
537 return newSession
538}
539
540// ClientConfig satisfies the client.ConfigProvider interface and is used to
541// configure the service client instances. Passing the Session to the service
542// client's constructor (New) will use this method to configure the client.
543func (s *Session) ClientConfig(serviceName string, cfgs ...*aws.Config) client.Config {
544 // Backwards compatibility, the error will be eaten if user calls ClientConfig
545 // directly. All SDK services will use ClientconfigWithError.
546 cfg, _ := s.clientConfigWithErr(serviceName, cfgs...)
547
548 return cfg
549}
550
551func (s *Session) clientConfigWithErr(serviceName string, cfgs ...*aws.Config) (client.Config, error) {
552 s = s.Copy(cfgs...)
553
554 var resolved endpoints.ResolvedEndpoint
555 var err error
556
557 region := aws.StringValue(s.Config.Region)
558
559 if endpoint := aws.StringValue(s.Config.Endpoint); len(endpoint) != 0 {
560 resolved.URL = endpoints.AddScheme(endpoint, aws.BoolValue(s.Config.DisableSSL))
561 resolved.SigningRegion = region
562 } else {
563 resolved, err = s.Config.EndpointResolver.EndpointFor(
564 serviceName, region,
565 func(opt *endpoints.Options) {
566 opt.DisableSSL = aws.BoolValue(s.Config.DisableSSL)
567 opt.UseDualStack = aws.BoolValue(s.Config.UseDualStack)
568
569 // Support the condition where the service is modeled but its
570 // endpoint metadata is not available.
571 opt.ResolveUnknownService = true
572 },
573 )
574 }
575
576 return client.Config{
15c0b25d
AP
577 Config: s.Config,
578 Handlers: s.Handlers,
579 Endpoint: resolved.URL,
580 SigningRegion: resolved.SigningRegion,
581 SigningNameDerived: resolved.SigningNameDerived,
582 SigningName: resolved.SigningName,
bae9f6d2
JC
583 }, err
584}
585
586// ClientConfigNoResolveEndpoint is the same as ClientConfig with the exception
587// that the EndpointResolver will not be used to resolve the endpoint. The only
588// endpoint set must come from the aws.Config.Endpoint field.
589func (s *Session) ClientConfigNoResolveEndpoint(cfgs ...*aws.Config) client.Config {
590 s = s.Copy(cfgs...)
591
592 var resolved endpoints.ResolvedEndpoint
593
594 region := aws.StringValue(s.Config.Region)
595
596 if ep := aws.StringValue(s.Config.Endpoint); len(ep) > 0 {
597 resolved.URL = endpoints.AddScheme(ep, aws.BoolValue(s.Config.DisableSSL))
598 resolved.SigningRegion = region
599 }
600
601 return client.Config{
15c0b25d
AP
602 Config: s.Config,
603 Handlers: s.Handlers,
604 Endpoint: resolved.URL,
605 SigningRegion: resolved.SigningRegion,
606 SigningNameDerived: resolved.SigningNameDerived,
607 SigningName: resolved.SigningName,
bae9f6d2
JC
608 }
609}