resolve.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  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. Logger: logging.NewStandardLogger(os.Stderr),
  27. ConfigSources: sources,
  28. }
  29. return nil
  30. }
  31. // resolveCustomCABundle extracts the first instance of a custom CA bundle filename
  32. // from the external configurations. It will update the HTTP Client's builder
  33. // to be configured with the custom CA bundle.
  34. //
  35. // Config provider used:
  36. // * customCABundleProvider
  37. func resolveCustomCABundle(ctx context.Context, cfg *aws.Config, cfgs configs) error {
  38. pemCerts, found, err := getCustomCABundle(ctx, cfgs)
  39. if err != nil {
  40. // TODO error handling, What is the best way to handle this?
  41. // capture previous errors continue. error out if all errors
  42. return err
  43. }
  44. if !found {
  45. return nil
  46. }
  47. if cfg.HTTPClient == nil {
  48. cfg.HTTPClient = awshttp.NewBuildableClient()
  49. }
  50. trOpts, ok := cfg.HTTPClient.(*awshttp.BuildableClient)
  51. if !ok {
  52. return fmt.Errorf("unable to add custom RootCAs HTTPClient, "+
  53. "has no WithTransportOptions, %T", cfg.HTTPClient)
  54. }
  55. var appendErr error
  56. client := trOpts.WithTransportOptions(func(tr *http.Transport) {
  57. if tr.TLSClientConfig == nil {
  58. tr.TLSClientConfig = &tls.Config{}
  59. }
  60. if tr.TLSClientConfig.RootCAs == nil {
  61. tr.TLSClientConfig.RootCAs = x509.NewCertPool()
  62. }
  63. b, err := ioutil.ReadAll(pemCerts)
  64. if err != nil {
  65. appendErr = fmt.Errorf("failed to read custom CA bundle PEM file")
  66. }
  67. if !tr.TLSClientConfig.RootCAs.AppendCertsFromPEM(b) {
  68. appendErr = fmt.Errorf("failed to load custom CA bundle PEM file")
  69. }
  70. })
  71. if appendErr != nil {
  72. return appendErr
  73. }
  74. cfg.HTTPClient = client
  75. return err
  76. }
  77. // resolveRegion extracts the first instance of a Region from the configs slice.
  78. //
  79. // Config providers used:
  80. // * regionProvider
  81. func resolveRegion(ctx context.Context, cfg *aws.Config, configs configs) error {
  82. v, found, err := getRegion(ctx, configs)
  83. if err != nil {
  84. // TODO error handling, What is the best way to handle this?
  85. // capture previous errors continue. error out if all errors
  86. return err
  87. }
  88. if !found {
  89. return nil
  90. }
  91. cfg.Region = v
  92. return nil
  93. }
  94. func resolveBaseEndpoint(ctx context.Context, cfg *aws.Config, configs configs) error {
  95. var downcastCfgSources []interface{}
  96. for _, cs := range configs {
  97. downcastCfgSources = append(downcastCfgSources, interface{}(cs))
  98. }
  99. if val, found, err := GetIgnoreConfiguredEndpoints(ctx, downcastCfgSources); found && val && err == nil {
  100. cfg.BaseEndpoint = nil
  101. return nil
  102. }
  103. v, found, err := getBaseEndpoint(ctx, configs)
  104. if err != nil {
  105. return err
  106. }
  107. if !found {
  108. return nil
  109. }
  110. cfg.BaseEndpoint = aws.String(v)
  111. return nil
  112. }
  113. // resolveAppID extracts the sdk app ID from the configs slice's SharedConfig or env var
  114. func resolveAppID(ctx context.Context, cfg *aws.Config, configs configs) error {
  115. ID, _, err := getAppID(ctx, configs)
  116. if err != nil {
  117. return err
  118. }
  119. cfg.AppID = ID
  120. return nil
  121. }
  122. // resolveDisableRequestCompression extracts the DisableRequestCompression from the configs slice's
  123. // SharedConfig or EnvConfig
  124. func resolveDisableRequestCompression(ctx context.Context, cfg *aws.Config, configs configs) error {
  125. disable, _, err := getDisableRequestCompression(ctx, configs)
  126. if err != nil {
  127. return err
  128. }
  129. cfg.DisableRequestCompression = disable
  130. return nil
  131. }
  132. // resolveRequestMinCompressSizeBytes extracts the RequestMinCompressSizeBytes from the configs slice's
  133. // SharedConfig or EnvConfig
  134. func resolveRequestMinCompressSizeBytes(ctx context.Context, cfg *aws.Config, configs configs) error {
  135. minBytes, found, err := getRequestMinCompressSizeBytes(ctx, configs)
  136. if err != nil {
  137. return err
  138. }
  139. // must set a default min size 10240 if not configured
  140. if !found {
  141. minBytes = 10240
  142. }
  143. cfg.RequestMinCompressSizeBytes = minBytes
  144. return nil
  145. }
  146. // resolveAccountIDEndpointMode extracts the AccountIDEndpointMode from the configs slice's
  147. // SharedConfig or EnvConfig
  148. func resolveAccountIDEndpointMode(ctx context.Context, cfg *aws.Config, configs configs) error {
  149. m, found, err := getAccountIDEndpointMode(ctx, configs)
  150. if err != nil {
  151. return err
  152. }
  153. if !found {
  154. m = aws.AccountIDEndpointModePreferred
  155. }
  156. cfg.AccountIDEndpointMode = m
  157. return nil
  158. }
  159. // resolveRequestChecksumCalculation extracts the RequestChecksumCalculation from the configs slice's
  160. // SharedConfig or EnvConfig
  161. func resolveRequestChecksumCalculation(ctx context.Context, cfg *aws.Config, configs configs) error {
  162. c, found, err := getRequestChecksumCalculation(ctx, configs)
  163. if err != nil {
  164. return err
  165. }
  166. if !found {
  167. c = aws.RequestChecksumCalculationWhenSupported
  168. }
  169. cfg.RequestChecksumCalculation = c
  170. return nil
  171. }
  172. // resolveResponseValidation extracts the ResponseChecksumValidation from the configs slice's
  173. // SharedConfig or EnvConfig
  174. func resolveResponseChecksumValidation(ctx context.Context, cfg *aws.Config, configs configs) error {
  175. c, found, err := getResponseChecksumValidation(ctx, configs)
  176. if err != nil {
  177. return err
  178. }
  179. if !found {
  180. c = aws.ResponseChecksumValidationWhenSupported
  181. }
  182. cfg.ResponseChecksumValidation = c
  183. return nil
  184. }
  185. // resolveDefaultRegion extracts the first instance of a default region and sets `aws.Config.Region` to the default
  186. // region if region had not been resolved from other sources.
  187. func resolveDefaultRegion(ctx context.Context, cfg *aws.Config, configs configs) error {
  188. if len(cfg.Region) > 0 {
  189. return nil
  190. }
  191. v, found, err := getDefaultRegion(ctx, configs)
  192. if err != nil {
  193. return err
  194. }
  195. if !found {
  196. return nil
  197. }
  198. cfg.Region = v
  199. return nil
  200. }
  201. // resolveHTTPClient extracts the first instance of a HTTPClient and sets `aws.Config.HTTPClient` to the HTTPClient instance
  202. // if one has not been resolved from other sources.
  203. func resolveHTTPClient(ctx context.Context, cfg *aws.Config, configs configs) error {
  204. c, found, err := getHTTPClient(ctx, configs)
  205. if err != nil {
  206. return err
  207. }
  208. if !found {
  209. return nil
  210. }
  211. cfg.HTTPClient = c
  212. return nil
  213. }
  214. // resolveAPIOptions extracts the first instance of APIOptions and sets `aws.Config.APIOptions` to the resolved API options
  215. // if one has not been resolved from other sources.
  216. func resolveAPIOptions(ctx context.Context, cfg *aws.Config, configs configs) error {
  217. o, found, err := getAPIOptions(ctx, configs)
  218. if err != nil {
  219. return err
  220. }
  221. if !found {
  222. return nil
  223. }
  224. cfg.APIOptions = o
  225. return nil
  226. }
  227. // resolveEndpointResolver extracts the first instance of a EndpointResolverFunc from the config slice
  228. // and sets the functions result on the aws.Config.EndpointResolver
  229. func resolveEndpointResolver(ctx context.Context, cfg *aws.Config, configs configs) error {
  230. endpointResolver, found, err := getEndpointResolver(ctx, configs)
  231. if err != nil {
  232. return err
  233. }
  234. if !found {
  235. return nil
  236. }
  237. cfg.EndpointResolver = endpointResolver
  238. return nil
  239. }
  240. // resolveEndpointResolver extracts the first instance of a EndpointResolverFunc from the config slice
  241. // and sets the functions result on the aws.Config.EndpointResolver
  242. func resolveEndpointResolverWithOptions(ctx context.Context, cfg *aws.Config, configs configs) error {
  243. endpointResolver, found, err := getEndpointResolverWithOptions(ctx, configs)
  244. if err != nil {
  245. return err
  246. }
  247. if !found {
  248. return nil
  249. }
  250. cfg.EndpointResolverWithOptions = endpointResolver
  251. return nil
  252. }
  253. func resolveLogger(ctx context.Context, cfg *aws.Config, configs configs) error {
  254. logger, found, err := getLogger(ctx, configs)
  255. if err != nil {
  256. return err
  257. }
  258. if !found {
  259. return nil
  260. }
  261. cfg.Logger = logger
  262. return nil
  263. }
  264. func resolveClientLogMode(ctx context.Context, cfg *aws.Config, configs configs) error {
  265. mode, found, err := getClientLogMode(ctx, configs)
  266. if err != nil {
  267. return err
  268. }
  269. if !found {
  270. return nil
  271. }
  272. cfg.ClientLogMode = mode
  273. return nil
  274. }
  275. func resolveRetryer(ctx context.Context, cfg *aws.Config, configs configs) error {
  276. retryer, found, err := getRetryer(ctx, configs)
  277. if err != nil {
  278. return err
  279. }
  280. if found {
  281. cfg.Retryer = retryer
  282. return nil
  283. }
  284. // Only load the retry options if a custom retryer has not be specified.
  285. if err = resolveRetryMaxAttempts(ctx, cfg, configs); err != nil {
  286. return err
  287. }
  288. return resolveRetryMode(ctx, cfg, configs)
  289. }
  290. func resolveEC2IMDSRegion(ctx context.Context, cfg *aws.Config, configs configs) error {
  291. if len(cfg.Region) > 0 {
  292. return nil
  293. }
  294. region, found, err := getEC2IMDSRegion(ctx, configs)
  295. if err != nil {
  296. return err
  297. }
  298. if !found {
  299. return nil
  300. }
  301. cfg.Region = region
  302. return nil
  303. }
  304. func resolveDefaultsModeOptions(ctx context.Context, cfg *aws.Config, configs configs) error {
  305. defaultsMode, found, err := getDefaultsMode(ctx, configs)
  306. if err != nil {
  307. return err
  308. }
  309. if !found {
  310. defaultsMode = aws.DefaultsModeLegacy
  311. }
  312. var environment aws.RuntimeEnvironment
  313. if defaultsMode == aws.DefaultsModeAuto {
  314. envConfig, _, _ := getAWSConfigSources(configs)
  315. client, found, err := getDefaultsModeIMDSClient(ctx, configs)
  316. if err != nil {
  317. return err
  318. }
  319. if !found {
  320. client = imds.NewFromConfig(*cfg)
  321. }
  322. environment, err = resolveDefaultsModeRuntimeEnvironment(ctx, envConfig, client)
  323. if err != nil {
  324. return err
  325. }
  326. }
  327. cfg.DefaultsMode = defaultsMode
  328. cfg.RuntimeEnvironment = environment
  329. return nil
  330. }
  331. func resolveRetryMaxAttempts(ctx context.Context, cfg *aws.Config, configs configs) error {
  332. maxAttempts, found, err := getRetryMaxAttempts(ctx, configs)
  333. if err != nil || !found {
  334. return err
  335. }
  336. cfg.RetryMaxAttempts = maxAttempts
  337. return nil
  338. }
  339. func resolveRetryMode(ctx context.Context, cfg *aws.Config, configs configs) error {
  340. retryMode, found, err := getRetryMode(ctx, configs)
  341. if err != nil || !found {
  342. return err
  343. }
  344. cfg.RetryMode = retryMode
  345. return nil
  346. }
  347. func resolveInterceptors(ctx context.Context, cfg *aws.Config, configs configs) error {
  348. // LoadOptions is the only thing that you can really configure interceptors
  349. // on so just check that directly.
  350. for _, c := range configs {
  351. if loadopts, ok := c.(LoadOptions); ok {
  352. cfg.Interceptors = loadopts.Interceptors.Copy()
  353. }
  354. }
  355. return nil
  356. }
  357. func resolveAuthSchemePreference(ctx context.Context, cfg *aws.Config, configs configs) error {
  358. if pref, ok := getAuthSchemePreference(ctx, configs); ok {
  359. cfg.AuthSchemePreference = pref
  360. }
  361. return nil
  362. }
  363. func resolveServiceOptions(ctx context.Context, cfg *aws.Config, configs configs) error {
  364. serviceOptions, found, err := getServiceOptions(ctx, configs)
  365. if err != nil {
  366. return err
  367. }
  368. if !found {
  369. return nil
  370. }
  371. cfg.ServiceOptions = serviceOptions
  372. return nil
  373. }