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 }