resolve.go 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. package config
  2. import (
  3. "context"
  4. "crypto/tls"
  5. "crypto/x509"
  6. "fmt"
  7. "io/ioutil"
  8. "net/http"
  9. "os"
  10. "github.com/aws/aws-sdk-go-v2/aws"
  11. awshttp "github.com/aws/aws-sdk-go-v2/aws/transport/http"
  12. "github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
  13. "github.com/aws/smithy-go/logging"
  14. )
  15. // resolveDefaultAWSConfig will write default configuration values into the cfg
  16. // value. It will write the default values, overwriting any previous value.
  17. //
  18. // This should be used as the first resolver in the slice of resolvers when
  19. // resolving external configuration.
  20. func resolveDefaultAWSConfig(ctx context.Context, cfg *aws.Config, cfgs configs) error {
  21. var sources []interface{}
  22. for _, s := range cfgs {
  23. sources = append(sources, s)
  24. }
  25. *cfg = aws.Config{
  26. Credentials: aws.AnonymousCredentials{},
  27. Logger: logging.NewStandardLogger(os.Stderr),
  28. ConfigSources: sources,
  29. }
  30. return nil
  31. }
  32. // resolveCustomCABundle extracts the first instance of a custom CA bundle filename
  33. // from the external configurations. It will update the HTTP Client's builder
  34. // to be configured with the custom CA bundle.
  35. //
  36. // Config provider used:
  37. // * customCABundleProvider
  38. func resolveCustomCABundle(ctx context.Context, cfg *aws.Config, cfgs configs) error {
  39. pemCerts, found, err := getCustomCABundle(ctx, cfgs)
  40. if err != nil {
  41. // TODO error handling, What is the best way to handle this?
  42. // capture previous errors continue. error out if all errors
  43. return err
  44. }
  45. if !found {
  46. return nil
  47. }
  48. if cfg.HTTPClient == nil {
  49. cfg.HTTPClient = awshttp.NewBuildableClient()
  50. }
  51. trOpts, ok := cfg.HTTPClient.(*awshttp.BuildableClient)
  52. if !ok {
  53. return fmt.Errorf("unable to add custom RootCAs HTTPClient, "+
  54. "has no WithTransportOptions, %T", cfg.HTTPClient)
  55. }
  56. var appendErr error
  57. client := trOpts.WithTransportOptions(func(tr *http.Transport) {
  58. if tr.TLSClientConfig == nil {
  59. tr.TLSClientConfig = &tls.Config{}
  60. }
  61. if tr.TLSClientConfig.RootCAs == nil {
  62. tr.TLSClientConfig.RootCAs = x509.NewCertPool()
  63. }
  64. b, err := ioutil.ReadAll(pemCerts)
  65. if err != nil {
  66. appendErr = fmt.Errorf("failed to read custom CA bundle PEM file")
  67. }
  68. if !tr.TLSClientConfig.RootCAs.AppendCertsFromPEM(b) {
  69. appendErr = fmt.Errorf("failed to load custom CA bundle PEM file")
  70. }
  71. })
  72. if appendErr != nil {
  73. return appendErr
  74. }
  75. cfg.HTTPClient = client
  76. return err
  77. }
  78. // resolveRegion extracts the first instance of a Region from the configs slice.
  79. //
  80. // Config providers used:
  81. // * regionProvider
  82. func resolveRegion(ctx context.Context, cfg *aws.Config, configs configs) error {
  83. v, found, err := getRegion(ctx, configs)
  84. if err != nil {
  85. // TODO error handling, What is the best way to handle this?
  86. // capture previous errors continue. error out if all errors
  87. return err
  88. }
  89. if !found {
  90. return nil
  91. }
  92. cfg.Region = v
  93. return nil
  94. }
  95. // resolveDefaultRegion extracts the first instance of a default region and sets `aws.Config.Region` to the default
  96. // region if region had not been resolved from other sources.
  97. func resolveDefaultRegion(ctx context.Context, cfg *aws.Config, configs configs) error {
  98. if len(cfg.Region) > 0 {
  99. return nil
  100. }
  101. v, found, err := getDefaultRegion(ctx, configs)
  102. if err != nil {
  103. return err
  104. }
  105. if !found {
  106. return nil
  107. }
  108. cfg.Region = v
  109. return nil
  110. }
  111. // resolveHTTPClient extracts the first instance of a HTTPClient and sets `aws.Config.HTTPClient` to the HTTPClient instance
  112. // if one has not been resolved from other sources.
  113. func resolveHTTPClient(ctx context.Context, cfg *aws.Config, configs configs) error {
  114. c, found, err := getHTTPClient(ctx, configs)
  115. if err != nil {
  116. return err
  117. }
  118. if !found {
  119. return nil
  120. }
  121. cfg.HTTPClient = c
  122. return nil
  123. }
  124. // resolveAPIOptions extracts the first instance of APIOptions and sets `aws.Config.APIOptions` to the resolved API options
  125. // if one has not been resolved from other sources.
  126. func resolveAPIOptions(ctx context.Context, cfg *aws.Config, configs configs) error {
  127. o, found, err := getAPIOptions(ctx, configs)
  128. if err != nil {
  129. return err
  130. }
  131. if !found {
  132. return nil
  133. }
  134. cfg.APIOptions = o
  135. return nil
  136. }
  137. // resolveEndpointResolver extracts the first instance of a EndpointResolverFunc from the config slice
  138. // and sets the functions result on the aws.Config.EndpointResolver
  139. func resolveEndpointResolver(ctx context.Context, cfg *aws.Config, configs configs) error {
  140. endpointResolver, found, err := getEndpointResolver(ctx, configs)
  141. if err != nil {
  142. return err
  143. }
  144. if !found {
  145. return nil
  146. }
  147. cfg.EndpointResolver = endpointResolver
  148. return nil
  149. }
  150. // resolveEndpointResolver extracts the first instance of a EndpointResolverFunc from the config slice
  151. // and sets the functions result on the aws.Config.EndpointResolver
  152. func resolveEndpointResolverWithOptions(ctx context.Context, cfg *aws.Config, configs configs) error {
  153. endpointResolver, found, err := getEndpointResolverWithOptions(ctx, configs)
  154. if err != nil {
  155. return err
  156. }
  157. if !found {
  158. return nil
  159. }
  160. cfg.EndpointResolverWithOptions = endpointResolver
  161. return nil
  162. }
  163. func resolveLogger(ctx context.Context, cfg *aws.Config, configs configs) error {
  164. logger, found, err := getLogger(ctx, configs)
  165. if err != nil {
  166. return err
  167. }
  168. if !found {
  169. return nil
  170. }
  171. cfg.Logger = logger
  172. return nil
  173. }
  174. func resolveClientLogMode(ctx context.Context, cfg *aws.Config, configs configs) error {
  175. mode, found, err := getClientLogMode(ctx, configs)
  176. if err != nil {
  177. return err
  178. }
  179. if !found {
  180. return nil
  181. }
  182. cfg.ClientLogMode = mode
  183. return nil
  184. }
  185. func resolveRetryer(ctx context.Context, cfg *aws.Config, configs configs) error {
  186. retryer, found, err := getRetryer(ctx, configs)
  187. if err != nil {
  188. return err
  189. }
  190. if found {
  191. cfg.Retryer = retryer
  192. return nil
  193. }
  194. // Only load the retry options if a custom retryer has not be specified.
  195. if err = resolveRetryMaxAttempts(ctx, cfg, configs); err != nil {
  196. return err
  197. }
  198. return resolveRetryMode(ctx, cfg, configs)
  199. }
  200. func resolveEC2IMDSRegion(ctx context.Context, cfg *aws.Config, configs configs) error {
  201. if len(cfg.Region) > 0 {
  202. return nil
  203. }
  204. region, found, err := getEC2IMDSRegion(ctx, configs)
  205. if err != nil {
  206. return err
  207. }
  208. if !found {
  209. return nil
  210. }
  211. cfg.Region = region
  212. return nil
  213. }
  214. func resolveDefaultsModeOptions(ctx context.Context, cfg *aws.Config, configs configs) error {
  215. defaultsMode, found, err := getDefaultsMode(ctx, configs)
  216. if err != nil {
  217. return err
  218. }
  219. if !found {
  220. defaultsMode = aws.DefaultsModeLegacy
  221. }
  222. var environment aws.RuntimeEnvironment
  223. if defaultsMode == aws.DefaultsModeAuto {
  224. envConfig, _, _ := getAWSConfigSources(configs)
  225. client, found, err := getDefaultsModeIMDSClient(ctx, configs)
  226. if err != nil {
  227. return err
  228. }
  229. if !found {
  230. client = imds.NewFromConfig(*cfg)
  231. }
  232. environment, err = resolveDefaultsModeRuntimeEnvironment(ctx, envConfig, client)
  233. if err != nil {
  234. return err
  235. }
  236. }
  237. cfg.DefaultsMode = defaultsMode
  238. cfg.RuntimeEnvironment = environment
  239. return nil
  240. }
  241. func resolveRetryMaxAttempts(ctx context.Context, cfg *aws.Config, configs configs) error {
  242. maxAttempts, found, err := getRetryMaxAttempts(ctx, configs)
  243. if err != nil || !found {
  244. return err
  245. }
  246. cfg.RetryMaxAttempts = maxAttempts
  247. return nil
  248. }
  249. func resolveRetryMode(ctx context.Context, cfg *aws.Config, configs configs) error {
  250. retryMode, found, err := getRetryMode(ctx, configs)
  251. if err != nil || !found {
  252. return err
  253. }
  254. cfg.RetryMode = retryMode
  255. return nil
  256. }