src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

resolve.go (11862B)


      1 package config
      2 
      3 import (
      4 	"context"
      5 	"crypto/tls"
      6 	"crypto/x509"
      7 	"fmt"
      8 	"io"
      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 []any
     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 := io.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 []any
    110 	for _, cs := range configs {
    111 		downcastCfgSources = append(downcastCfgSources, any(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 // resolveDisableClockSkewCorrection extracts the DisableClockSkewCorrection from
    155 // the configs slice's SharedConfig or EnvConfig
    156 func resolveDisableClockSkewCorrection(ctx context.Context, cfg *aws.Config, configs configs) error {
    157 	disable, _, err := getDisableClockSkewCorrection(ctx, configs)
    158 	if err != nil {
    159 		return err
    160 	}
    161 
    162 	cfg.DisableClockSkewCorrection = disable
    163 	return nil
    164 }
    165 
    166 // resolveRequestMinCompressSizeBytes extracts the RequestMinCompressSizeBytes from the configs slice's
    167 // SharedConfig or EnvConfig
    168 func resolveRequestMinCompressSizeBytes(ctx context.Context, cfg *aws.Config, configs configs) error {
    169 	minBytes, found, err := getRequestMinCompressSizeBytes(ctx, configs)
    170 	if err != nil {
    171 		return err
    172 	}
    173 	// must set a default min size 10240 if not configured
    174 	if !found {
    175 		minBytes = 10240
    176 	}
    177 	cfg.RequestMinCompressSizeBytes = minBytes
    178 	return nil
    179 }
    180 
    181 // resolveAccountIDEndpointMode extracts the AccountIDEndpointMode from the configs slice's
    182 // SharedConfig or EnvConfig
    183 func resolveAccountIDEndpointMode(ctx context.Context, cfg *aws.Config, configs configs) error {
    184 	m, found, err := getAccountIDEndpointMode(ctx, configs)
    185 	if err != nil {
    186 		return err
    187 	}
    188 
    189 	if !found {
    190 		m = aws.AccountIDEndpointModePreferred
    191 	}
    192 
    193 	cfg.AccountIDEndpointMode = m
    194 	return nil
    195 }
    196 
    197 // resolveRequestChecksumCalculation extracts the RequestChecksumCalculation from the configs slice's
    198 // SharedConfig or EnvConfig
    199 func resolveRequestChecksumCalculation(ctx context.Context, cfg *aws.Config, configs configs) error {
    200 	c, found, err := getRequestChecksumCalculation(ctx, configs)
    201 	if err != nil {
    202 		return err
    203 	}
    204 
    205 	if !found {
    206 		c = aws.RequestChecksumCalculationWhenSupported
    207 	}
    208 	cfg.RequestChecksumCalculation = c
    209 	return nil
    210 }
    211 
    212 // resolveResponseValidation extracts the ResponseChecksumValidation from the configs slice's
    213 // SharedConfig or EnvConfig
    214 func resolveResponseChecksumValidation(ctx context.Context, cfg *aws.Config, configs configs) error {
    215 	c, found, err := getResponseChecksumValidation(ctx, configs)
    216 	if err != nil {
    217 		return err
    218 	}
    219 
    220 	if !found {
    221 		c = aws.ResponseChecksumValidationWhenSupported
    222 	}
    223 	cfg.ResponseChecksumValidation = c
    224 	return nil
    225 }
    226 
    227 // resolveDefaultRegion extracts the first instance of a default region and sets `aws.Config.Region` to the default
    228 // region if region had not been resolved from other sources.
    229 func resolveDefaultRegion(ctx context.Context, cfg *aws.Config, configs configs) error {
    230 	if len(cfg.Region) > 0 {
    231 		return nil
    232 	}
    233 
    234 	v, found, err := getDefaultRegion(ctx, configs)
    235 	if err != nil {
    236 		return err
    237 	}
    238 	if !found {
    239 		return nil
    240 	}
    241 
    242 	cfg.Region = v
    243 
    244 	return nil
    245 }
    246 
    247 // resolveHTTPClient extracts the first instance of a HTTPClient and sets `aws.Config.HTTPClient` to the HTTPClient instance
    248 // if one has not been resolved from other sources.
    249 func resolveHTTPClient(ctx context.Context, cfg *aws.Config, configs configs) error {
    250 	c, found, err := getHTTPClient(ctx, configs)
    251 	if err != nil {
    252 		return err
    253 	}
    254 	if !found {
    255 		return nil
    256 	}
    257 
    258 	cfg.HTTPClient = c
    259 	return nil
    260 }
    261 
    262 // resolveAPIOptions extracts the first instance of APIOptions and sets `aws.Config.APIOptions` to the resolved API options
    263 // if one has not been resolved from other sources.
    264 func resolveAPIOptions(ctx context.Context, cfg *aws.Config, configs configs) error {
    265 	o, found, err := getAPIOptions(ctx, configs)
    266 	if err != nil {
    267 		return err
    268 	}
    269 	if !found {
    270 		return nil
    271 	}
    272 
    273 	cfg.APIOptions = o
    274 
    275 	return nil
    276 }
    277 
    278 // resolveEndpointResolver extracts the first instance of a EndpointResolverFunc from the config slice
    279 // and sets the functions result on the aws.Config.EndpointResolver
    280 func resolveEndpointResolver(ctx context.Context, cfg *aws.Config, configs configs) error {
    281 	endpointResolver, found, err := getEndpointResolver(ctx, configs)
    282 	if err != nil {
    283 		return err
    284 	}
    285 	if !found {
    286 		return nil
    287 	}
    288 
    289 	cfg.EndpointResolver = endpointResolver
    290 
    291 	return nil
    292 }
    293 
    294 // resolveEndpointResolver extracts the first instance of a EndpointResolverFunc from the config slice
    295 // and sets the functions result on the aws.Config.EndpointResolver
    296 func resolveEndpointResolverWithOptions(ctx context.Context, cfg *aws.Config, configs configs) error {
    297 	endpointResolver, found, err := getEndpointResolverWithOptions(ctx, configs)
    298 	if err != nil {
    299 		return err
    300 	}
    301 	if !found {
    302 		return nil
    303 	}
    304 
    305 	cfg.EndpointResolverWithOptions = endpointResolver
    306 
    307 	return nil
    308 }
    309 
    310 func resolveLogger(ctx context.Context, cfg *aws.Config, configs configs) error {
    311 	logger, found, err := getLogger(ctx, configs)
    312 	if err != nil {
    313 		return err
    314 	}
    315 	if !found {
    316 		return nil
    317 	}
    318 
    319 	cfg.Logger = logger
    320 
    321 	return nil
    322 }
    323 
    324 func resolveClientLogMode(ctx context.Context, cfg *aws.Config, configs configs) error {
    325 	mode, found, err := getClientLogMode(ctx, configs)
    326 	if err != nil {
    327 		return err
    328 	}
    329 	if !found {
    330 		return nil
    331 	}
    332 
    333 	cfg.ClientLogMode = mode
    334 
    335 	return nil
    336 }
    337 
    338 func resolveRetryer(ctx context.Context, cfg *aws.Config, configs configs) error {
    339 	retryer, found, err := getRetryer(ctx, configs)
    340 	if err != nil {
    341 		return err
    342 	}
    343 
    344 	if found {
    345 		cfg.Retryer = retryer
    346 		return nil
    347 	}
    348 
    349 	// Only load the retry options if a custom retryer has not be specified.
    350 	if err = resolveRetryMaxAttempts(ctx, cfg, configs); err != nil {
    351 		return err
    352 	}
    353 	return resolveRetryMode(ctx, cfg, configs)
    354 }
    355 
    356 func resolveEC2IMDSRegion(ctx context.Context, cfg *aws.Config, configs configs) error {
    357 	if len(cfg.Region) > 0 {
    358 		return nil
    359 	}
    360 
    361 	region, found, err := getEC2IMDSRegion(ctx, configs)
    362 	if err != nil {
    363 		return err
    364 	}
    365 	if !found {
    366 		return nil
    367 	}
    368 
    369 	cfg.Region = region
    370 
    371 	return nil
    372 }
    373 
    374 func resolveDefaultsModeOptions(ctx context.Context, cfg *aws.Config, configs configs) error {
    375 	defaultsMode, found, err := getDefaultsMode(ctx, configs)
    376 	if err != nil {
    377 		return err
    378 	}
    379 	if !found {
    380 		defaultsMode = aws.DefaultsModeLegacy
    381 	}
    382 
    383 	var environment aws.RuntimeEnvironment
    384 	if defaultsMode == aws.DefaultsModeAuto {
    385 		envConfig, _, _ := getAWSConfigSources(configs)
    386 
    387 		client, found, err := getDefaultsModeIMDSClient(ctx, configs)
    388 		if err != nil {
    389 			return err
    390 		}
    391 		if !found {
    392 			client = imds.NewFromConfig(*cfg)
    393 		}
    394 
    395 		environment, err = resolveDefaultsModeRuntimeEnvironment(ctx, envConfig, client)
    396 		if err != nil {
    397 			return err
    398 		}
    399 	}
    400 
    401 	cfg.DefaultsMode = defaultsMode
    402 	cfg.RuntimeEnvironment = environment
    403 
    404 	return nil
    405 }
    406 
    407 func resolveRetryMaxAttempts(ctx context.Context, cfg *aws.Config, configs configs) error {
    408 	maxAttempts, found, err := getRetryMaxAttempts(ctx, configs)
    409 	if err != nil || !found {
    410 		return err
    411 	}
    412 	cfg.RetryMaxAttempts = maxAttempts
    413 
    414 	return nil
    415 }
    416 
    417 func resolveRetryMode(ctx context.Context, cfg *aws.Config, configs configs) error {
    418 	retryMode, found, err := getRetryMode(ctx, configs)
    419 	if err != nil || !found {
    420 		return err
    421 	}
    422 	cfg.RetryMode = retryMode
    423 
    424 	return nil
    425 }
    426 
    427 func resolveInterceptors(ctx context.Context, cfg *aws.Config, configs configs) error {
    428 	// LoadOptions is the only thing that you can really configure interceptors
    429 	// on so just check that directly.
    430 	for _, c := range configs {
    431 		if loadopts, ok := c.(LoadOptions); ok {
    432 			cfg.Interceptors = loadopts.Interceptors.Copy()
    433 		}
    434 	}
    435 	return nil
    436 }
    437 
    438 func resolveAuthSchemePreference(ctx context.Context, cfg *aws.Config, configs configs) error {
    439 	if pref, ok := getAuthSchemePreference(ctx, configs); ok {
    440 		cfg.AuthSchemePreference = pref
    441 	}
    442 	return nil
    443 }
    444 
    445 func resolveServiceOptions(ctx context.Context, cfg *aws.Config, configs configs) error {
    446 	serviceOptions, found, err := getServiceOptions(ctx, configs)
    447 	if err != nil {
    448 		return err
    449 	}
    450 	if !found {
    451 		return nil
    452 	}
    453 
    454 	cfg.ServiceOptions = serviceOptions
    455 	return nil
    456 }
    457 
    458 func resolveRestrictFilePermissions(ctx context.Context, cfg *aws.Config, configs configs) error {
    459 	m, found, err := getRestrictFilePermissions(ctx, configs)
    460 	if err != nil {
    461 		return err
    462 	}
    463 
    464 	if !found {
    465 		m = aws.RestrictFilePermissionsUserReadWrite
    466 	}
    467 
    468 	cfg.RestrictFilePermissions = m
    469 	return nil
    470 }