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