defaults.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. // Package defaults is a collection of helpers to retrieve the SDK's default
  2. // configuration and handlers.
  3. //
  4. // Generally this package shouldn't be used directly, but session.Session
  5. // instead. This package is useful when you need to reset the defaults
  6. // of a session or service client to the SDK defaults before setting
  7. // additional parameters.
  8. package defaults
  9. import (
  10. "fmt"
  11. "net"
  12. "net/http"
  13. "net/url"
  14. "os"
  15. "time"
  16. "github.com/aws/aws-sdk-go/aws"
  17. "github.com/aws/aws-sdk-go/aws/awserr"
  18. "github.com/aws/aws-sdk-go/aws/corehandlers"
  19. "github.com/aws/aws-sdk-go/aws/credentials"
  20. "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
  21. "github.com/aws/aws-sdk-go/aws/credentials/endpointcreds"
  22. "github.com/aws/aws-sdk-go/aws/ec2metadata"
  23. "github.com/aws/aws-sdk-go/aws/endpoints"
  24. "github.com/aws/aws-sdk-go/aws/request"
  25. )
  26. // A Defaults provides a collection of default values for SDK clients.
  27. type Defaults struct {
  28. Config *aws.Config
  29. Handlers request.Handlers
  30. }
  31. // Get returns the SDK's default values with Config and handlers pre-configured.
  32. func Get() Defaults {
  33. cfg := Config()
  34. handlers := Handlers()
  35. cfg.Credentials = CredChain(cfg, handlers)
  36. return Defaults{
  37. Config: cfg,
  38. Handlers: handlers,
  39. }
  40. }
  41. // Config returns the default configuration without credentials.
  42. // To retrieve a config with credentials also included use
  43. // `defaults.Get().Config` instead.
  44. //
  45. // Generally you shouldn't need to use this method directly, but
  46. // is available if you need to reset the configuration of an
  47. // existing service client or session.
  48. func Config() *aws.Config {
  49. return aws.NewConfig().
  50. WithCredentials(credentials.AnonymousCredentials).
  51. WithRegion(os.Getenv("AWS_REGION")).
  52. WithHTTPClient(http.DefaultClient).
  53. WithMaxRetries(aws.UseServiceDefaultRetries).
  54. WithLogger(aws.NewDefaultLogger()).
  55. WithLogLevel(aws.LogOff).
  56. WithEndpointResolver(endpoints.DefaultResolver())
  57. }
  58. // Handlers returns the default request handlers.
  59. //
  60. // Generally you shouldn't need to use this method directly, but
  61. // is available if you need to reset the request handlers of an
  62. // existing service client or session.
  63. func Handlers() request.Handlers {
  64. var handlers request.Handlers
  65. handlers.Validate.PushBackNamed(corehandlers.ValidateEndpointHandler)
  66. handlers.Validate.AfterEachFn = request.HandlerListStopOnError
  67. handlers.Build.PushBackNamed(corehandlers.SDKVersionUserAgentHandler)
  68. handlers.Build.AfterEachFn = request.HandlerListStopOnError
  69. handlers.Sign.PushBackNamed(corehandlers.BuildContentLengthHandler)
  70. handlers.Send.PushBackNamed(corehandlers.ValidateReqSigHandler)
  71. handlers.Send.PushBackNamed(corehandlers.SendHandler)
  72. handlers.AfterRetry.PushBackNamed(corehandlers.AfterRetryHandler)
  73. handlers.ValidateResponse.PushBackNamed(corehandlers.ValidateResponseHandler)
  74. return handlers
  75. }
  76. // CredChain returns the default credential chain.
  77. //
  78. // Generally you shouldn't need to use this method directly, but
  79. // is available if you need to reset the credentials of an
  80. // existing service client or session's Config.
  81. func CredChain(cfg *aws.Config, handlers request.Handlers) *credentials.Credentials {
  82. return credentials.NewCredentials(&credentials.ChainProvider{
  83. VerboseErrors: aws.BoolValue(cfg.CredentialsChainVerboseErrors),
  84. Providers: []credentials.Provider{
  85. &credentials.EnvProvider{},
  86. &credentials.SharedCredentialsProvider{Filename: "", Profile: ""},
  87. RemoteCredProvider(*cfg, handlers),
  88. },
  89. })
  90. }
  91. const (
  92. httpProviderEnvVar = "AWS_CONTAINER_CREDENTIALS_FULL_URI"
  93. ecsCredsProviderEnvVar = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"
  94. )
  95. // RemoteCredProvider returns a credentials provider for the default remote
  96. // endpoints such as EC2 or ECS Roles.
  97. func RemoteCredProvider(cfg aws.Config, handlers request.Handlers) credentials.Provider {
  98. if u := os.Getenv(httpProviderEnvVar); len(u) > 0 {
  99. return localHTTPCredProvider(cfg, handlers, u)
  100. }
  101. if uri := os.Getenv(ecsCredsProviderEnvVar); len(uri) > 0 {
  102. u := fmt.Sprintf("http://169.254.170.2%s", uri)
  103. return httpCredProvider(cfg, handlers, u)
  104. }
  105. return ec2RoleProvider(cfg, handlers)
  106. }
  107. var lookupHostFn = net.LookupHost
  108. func isLoopbackHost(host string) (bool, error) {
  109. ip := net.ParseIP(host)
  110. if ip != nil {
  111. return ip.IsLoopback(), nil
  112. }
  113. // Host is not an ip, perform lookup
  114. addrs, err := lookupHostFn(host)
  115. if err != nil {
  116. return false, err
  117. }
  118. for _, addr := range addrs {
  119. if !net.ParseIP(addr).IsLoopback() {
  120. return false, nil
  121. }
  122. }
  123. return true, nil
  124. }
  125. func localHTTPCredProvider(cfg aws.Config, handlers request.Handlers, u string) credentials.Provider {
  126. var errMsg string
  127. parsed, err := url.Parse(u)
  128. if err != nil {
  129. errMsg = fmt.Sprintf("invalid URL, %v", err)
  130. } else {
  131. host := aws.URLHostname(parsed)
  132. if len(host) == 0 {
  133. errMsg = "unable to parse host from local HTTP cred provider URL"
  134. } else if isLoopback, loopbackErr := isLoopbackHost(host); loopbackErr != nil {
  135. errMsg = fmt.Sprintf("failed to resolve host %q, %v", host, loopbackErr)
  136. } else if !isLoopback {
  137. errMsg = fmt.Sprintf("invalid endpoint host, %q, only loopback hosts are allowed.", host)
  138. }
  139. }
  140. if len(errMsg) > 0 {
  141. if cfg.Logger != nil {
  142. cfg.Logger.Log("Ignoring, HTTP credential provider", errMsg, err)
  143. }
  144. return credentials.ErrorProvider{
  145. Err: awserr.New("CredentialsEndpointError", errMsg, err),
  146. ProviderName: endpointcreds.ProviderName,
  147. }
  148. }
  149. return httpCredProvider(cfg, handlers, u)
  150. }
  151. func httpCredProvider(cfg aws.Config, handlers request.Handlers, u string) credentials.Provider {
  152. return endpointcreds.NewProviderClient(cfg, handlers, u,
  153. func(p *endpointcreds.Provider) {
  154. p.ExpiryWindow = 5 * time.Minute
  155. },
  156. )
  157. }
  158. func ec2RoleProvider(cfg aws.Config, handlers request.Handlers) credentials.Provider {
  159. resolver := cfg.EndpointResolver
  160. if resolver == nil {
  161. resolver = endpoints.DefaultResolver()
  162. }
  163. e, _ := resolver.EndpointFor(endpoints.Ec2metadataServiceID, "")
  164. return &ec2rolecreds.EC2RoleProvider{
  165. Client: ec2metadata.NewClient(cfg, handlers, e.URL, e.SigningRegion),
  166. ExpiryWindow: 5 * time.Minute,
  167. }
  168. }