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