defaults.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  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.PushBackNamed(corehandlers.AddHostExecEnvUserAgentHander)
  69. handlers.Build.AfterEachFn = request.HandlerListStopOnError
  70. handlers.Sign.PushBackNamed(corehandlers.BuildContentLengthHandler)
  71. handlers.Send.PushBackNamed(corehandlers.ValidateReqSigHandler)
  72. handlers.Send.PushBackNamed(corehandlers.SendHandler)
  73. handlers.AfterRetry.PushBackNamed(corehandlers.AfterRetryHandler)
  74. handlers.ValidateResponse.PushBackNamed(corehandlers.ValidateResponseHandler)
  75. return handlers
  76. }
  77. // CredChain returns the default credential chain.
  78. //
  79. // Generally you shouldn't need to use this method directly, but
  80. // is available if you need to reset the credentials of an
  81. // existing service client or session's Config.
  82. func CredChain(cfg *aws.Config, handlers request.Handlers) *credentials.Credentials {
  83. return credentials.NewCredentials(&credentials.ChainProvider{
  84. VerboseErrors: aws.BoolValue(cfg.CredentialsChainVerboseErrors),
  85. Providers: []credentials.Provider{
  86. &credentials.EnvProvider{},
  87. &credentials.SharedCredentialsProvider{Filename: "", Profile: ""},
  88. RemoteCredProvider(*cfg, handlers),
  89. },
  90. })
  91. }
  92. const (
  93. httpProviderEnvVar = "AWS_CONTAINER_CREDENTIALS_FULL_URI"
  94. ecsCredsProviderEnvVar = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"
  95. )
  96. // RemoteCredProvider returns a credentials provider for the default remote
  97. // endpoints such as EC2 or ECS Roles.
  98. func RemoteCredProvider(cfg aws.Config, handlers request.Handlers) credentials.Provider {
  99. if u := os.Getenv(httpProviderEnvVar); len(u) > 0 {
  100. return localHTTPCredProvider(cfg, handlers, u)
  101. }
  102. if uri := os.Getenv(ecsCredsProviderEnvVar); len(uri) > 0 {
  103. u := fmt.Sprintf("http://169.254.170.2%s", uri)
  104. return httpCredProvider(cfg, handlers, u)
  105. }
  106. return ec2RoleProvider(cfg, handlers)
  107. }
  108. var lookupHostFn = net.LookupHost
  109. func isLoopbackHost(host string) (bool, error) {
  110. ip := net.ParseIP(host)
  111. if ip != nil {
  112. return ip.IsLoopback(), nil
  113. }
  114. // Host is not an ip, perform lookup
  115. addrs, err := lookupHostFn(host)
  116. if err != nil {
  117. return false, err
  118. }
  119. for _, addr := range addrs {
  120. if !net.ParseIP(addr).IsLoopback() {
  121. return false, nil
  122. }
  123. }
  124. return true, nil
  125. }
  126. func localHTTPCredProvider(cfg aws.Config, handlers request.Handlers, u string) credentials.Provider {
  127. var errMsg string
  128. parsed, err := url.Parse(u)
  129. if err != nil {
  130. errMsg = fmt.Sprintf("invalid URL, %v", err)
  131. } else {
  132. host := aws.URLHostname(parsed)
  133. if len(host) == 0 {
  134. errMsg = "unable to parse host from local HTTP cred provider URL"
  135. } else if isLoopback, loopbackErr := isLoopbackHost(host); loopbackErr != nil {
  136. errMsg = fmt.Sprintf("failed to resolve host %q, %v", host, loopbackErr)
  137. } else if !isLoopback {
  138. errMsg = fmt.Sprintf("invalid endpoint host, %q, only loopback hosts are allowed.", host)
  139. }
  140. }
  141. if len(errMsg) > 0 {
  142. if cfg.Logger != nil {
  143. cfg.Logger.Log("Ignoring, HTTP credential provider", errMsg, err)
  144. }
  145. return credentials.ErrorProvider{
  146. Err: awserr.New("CredentialsEndpointError", errMsg, err),
  147. ProviderName: endpointcreds.ProviderName,
  148. }
  149. }
  150. return httpCredProvider(cfg, handlers, u)
  151. }
  152. func httpCredProvider(cfg aws.Config, handlers request.Handlers, u string) credentials.Provider {
  153. return endpointcreds.NewProviderClient(cfg, handlers, u,
  154. func(p *endpointcreds.Provider) {
  155. p.ExpiryWindow = 5 * time.Minute
  156. },
  157. )
  158. }
  159. func ec2RoleProvider(cfg aws.Config, handlers request.Handlers) credentials.Provider {
  160. resolver := cfg.EndpointResolver
  161. if resolver == nil {
  162. resolver = endpoints.DefaultResolver()
  163. }
  164. e, _ := resolver.EndpointFor(endpoints.Ec2metadataServiceID, "")
  165. return &ec2rolecreds.EC2RoleProvider{
  166. Client: ec2metadata.NewClient(cfg, handlers, e.URL, e.SigningRegion),
  167. ExpiryWindow: 5 * time.Minute,
  168. }
  169. }