chore: upgrade dependencies

This commit is contained in:
2022-06-09 12:30:53 +02:00
parent 7203f3d6a1
commit dcb93ec8f7
518 changed files with 27809 additions and 3222 deletions

View File

@@ -1,3 +1,90 @@
# v1.15.10 (2022-06-07)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.15.9 (2022-05-26)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.15.8 (2022-05-25)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.15.7 (2022-05-17)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.15.6 (2022-05-16)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.15.5 (2022-05-09)
* **Bug Fix**: Fixes a bug in LoadDefaultConfig to correctly assign ConfigSources so all config resolvers have access to the config sources. This fixes the feature/ec2/imds client not having configuration applied via config.LoadOptions such as EC2IMDSClientEnableState. PR [#1682](https://github.com/aws/aws-sdk-go-v2/pull/1682)
# v1.15.4 (2022-04-25)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.15.3 (2022-03-30)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.15.2 (2022-03-24)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.15.1 (2022-03-23)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.15.0 (2022-03-08)
* **Feature**: Updated `github.com/aws/smithy-go` to latest version
* **Dependency Update**: Updated to the latest SDK module versions
# v1.14.0 (2022-02-24)
* **Feature**: Adds support for loading RetryMaxAttempts and RetryMod from the environment and shared configuration files. These parameters drive how the SDK's API client will initialize its default retryer, if custome retryer has not been specified. See [config](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/config) module and [aws.Config](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/aws#Config) for more information about and how to use these new options.
* **Feature**: Adds support for the `ca_bundle` parameter in shared config and credentials files. The usage of the file is the same as environment variable, `AWS_CA_BUNDLE`, but sourced from shared config. Fixes [#1589](https://github.com/aws/aws-sdk-go-v2/issues/1589)
* **Feature**: Updated `github.com/aws/smithy-go` to latest version
* **Dependency Update**: Updated to the latest SDK module versions
# v1.13.1 (2022-01-28)
* **Bug Fix**: Fixes LoadDefaultConfig handling of errors returned by passed in functional options. Previously errors returned from the LoadOptions passed into LoadDefaultConfig were incorrectly ignored. [#1562](https://github.com/aws/aws-sdk-go-v2/pull/1562). Thanks to [Pinglei Guo](https://github.com/pingleig) for submitting this PR.
* **Bug Fix**: Fixes the SDK's handling of `duration_sections` in the shared credentials file or specified in multiple shared config and shared credentials files under the same profile. [#1568](https://github.com/aws/aws-sdk-go-v2/pull/1568). Thanks to [Amir Szekely](https://github.com/kichik) for help reproduce this bug.
* **Bug Fix**: Updates `config` module to use os.UserHomeDir instead of hard coded environment variable for OS. [#1563](https://github.com/aws/aws-sdk-go-v2/pull/1563)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.13.0 (2022-01-14)
* **Feature**: Updated `github.com/aws/smithy-go` to latest version
* **Dependency Update**: Updated to the latest SDK module versions
# v1.12.0 (2022-01-07)
* **Feature**: Add load option for CredentialCache. Adds a new member to the LoadOptions struct, CredentialsCacheOptions. This member allows specifying a function that will be used to configure the CredentialsCache. The CredentialsCacheOptions will only be used if the configuration loader will wrap the underlying credential provider in the CredentialsCache.
* **Feature**: Updated `github.com/aws/smithy-go` to latest version
* **Dependency Update**: Updated to the latest SDK module versions
# v1.11.1 (2021-12-21)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.11.0 (2021-12-02)
* **Feature**: Add support for specifying `EndpointResolverWithOptions` on `LoadOptions`, and associated `WithEndpointResolverWithOptions`.
* **Dependency Update**: Updated to the latest SDK module versions
# v1.10.3 (2021-11-30)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.10.2 (2021-11-19)
* **Dependency Update**: Updated to the latest SDK module versions
# v1.10.1 (2021-11-12)
* **Dependency Update**: Updated to the latest SDK module versions

View File

@@ -2,6 +2,7 @@ package config
import (
"context"
"github.com/aws/aws-sdk-go-v2/aws"
)
@@ -34,8 +35,11 @@ var defaultAWSConfigResolvers = []awsConfigResolver{
// Sets the endpoint resolving behavior the API Clients will use for making
// requests to. Clients default to their own clients this allows overrides
// to be specified.
// to be specified. The resolveEndpointResolver option is deprecated, but
// we still need to set it for backwards compatibility on config
// construction.
resolveEndpointResolver,
resolveEndpointResolverWithOptions,
// Sets the retry behavior API clients will use within their retry attempt
// middleware. Defaults to unset, allowing API clients to define their own
@@ -51,6 +55,15 @@ var defaultAWSConfigResolvers = []awsConfigResolver{
// API client request pipeline middleware.
resolveAPIOptions,
// Resolves the DefaultsMode that should be used by SDK clients. If this
// mode is set to DefaultsModeAuto.
//
// Comes after HTTPClient and CustomCABundle to ensure the HTTP client is
// configured if provided before invoking IMDS if mode is auto. Comes
// before resolving credentials so that those subsequent clients use the
// configured auto mode.
resolveDefaultsModeOptions,
// Sets the resolved credentials the API clients will use for
// authentication. Provides the SDK's default credential chain.
//
@@ -124,17 +137,10 @@ func (cs configs) ResolveAWSConfig(ctx context.Context, resolvers []awsConfigRes
for _, fn := range resolvers {
if err := fn(ctx, &cfg, cs); err != nil {
// TODO provide better error?
return aws.Config{}, err
}
}
var sources []interface{}
for _, s := range cs {
sources = append(sources, s)
}
cfg.ConfigSources = sources
return cfg, nil
}
@@ -170,7 +176,9 @@ func (cs configs) ResolveConfig(f func(configs []interface{}) error) error {
func LoadDefaultConfig(ctx context.Context, optFns ...func(*LoadOptions) error) (cfg aws.Config, err error) {
var options LoadOptions
for _, optFn := range optFns {
optFn(&options)
if err := optFn(&options); err != nil {
return aws.Config{}, err
}
}
// assign Load Options to configs

View File

@@ -0,0 +1,47 @@
package config
import (
"context"
"os"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
)
const execEnvVar = "AWS_EXECUTION_ENV"
// DefaultsModeOptions is the set of options that are used to configure
type DefaultsModeOptions struct {
// The SDK configuration defaults mode. Defaults to legacy if not specified.
//
// Supported modes are: auto, cross-region, in-region, legacy, mobile, standard
Mode aws.DefaultsMode
// The EC2 Instance Metadata Client that should be used when performing environment
// discovery when aws.DefaultsModeAuto is set.
//
// If not specified the SDK will construct a client if the instance metadata service has not been disabled by
// the AWS_EC2_METADATA_DISABLED environment variable.
IMDSClient *imds.Client
}
func resolveDefaultsModeRuntimeEnvironment(ctx context.Context, envConfig *EnvConfig, client *imds.Client) (aws.RuntimeEnvironment, error) {
getRegionOutput, err := client.GetRegion(ctx, &imds.GetRegionInput{})
// honor context timeouts, but if we couldn't talk to IMDS don't fail runtime environment introspection.
select {
case <-ctx.Done():
return aws.RuntimeEnvironment{}, err
default:
}
var imdsRegion string
if err == nil {
imdsRegion = getRegionOutput.Region
}
return aws.RuntimeEnvironment{
EnvironmentIdentifier: aws.ExecutionEnvironmentID(os.Getenv(execEnvVar)),
Region: envConfig.Region,
EC2InstanceMetadataRegion: imdsRegion,
}, nil
}

View File

@@ -4,13 +4,14 @@ import (
"bytes"
"context"
"fmt"
"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
"io"
"io/ioutil"
"os"
"strconv"
"strings"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
)
// CredentialsSourceName provides a name of the provider when config is
@@ -63,6 +64,11 @@ const (
awsUseDualStackEndpoint = "AWS_USE_DUALSTACK_ENDPOINT"
awsUseFIPSEndpoint = "AWS_USE_FIPS_ENDPOINT"
awsDefaultMode = "AWS_DEFAULTS_MODE"
awsRetryMaxAttempts = "AWS_MAX_ATTEMPTS"
awsRetryMode = "AWS_RETRY_MODE"
)
var (
@@ -226,6 +232,22 @@ type EnvConfig struct {
//
// AWS_USE_FIPS_ENDPOINT=true
UseFIPSEndpoint aws.FIPSEndpointState
// Specifies the SDK Defaults Mode used by services.
//
// AWS_DEFAULTS_MODE=standard
DefaultsMode aws.DefaultsMode
// Specifies the maximum number attempts an API client will call an
// operation that fails with a retryable error.
//
// AWS_MAX_ATTEMPTS=3
RetryMaxAttempts int
// Specifies the retry model the API client will be created with.
//
// aws_retry_mode=standard
RetryMode aws.RetryMode
}
// loadEnvConfig reads configuration values from the OS's environment variables.
@@ -292,9 +314,45 @@ func NewEnvConfig() (EnvConfig, error) {
return cfg, err
}
if err := setDefaultsModeFromEnvVal(&cfg.DefaultsMode, []string{awsDefaultMode}); err != nil {
return cfg, err
}
if err := setIntFromEnvVal(&cfg.RetryMaxAttempts, []string{awsRetryMaxAttempts}); err != nil {
return cfg, err
}
if err := setRetryModeFromEnvVal(&cfg.RetryMode, []string{awsRetryMode}); err != nil {
return cfg, err
}
return cfg, nil
}
func (c EnvConfig) getDefaultsMode(ctx context.Context) (aws.DefaultsMode, bool, error) {
if len(c.DefaultsMode) == 0 {
return "", false, nil
}
return c.DefaultsMode, true, nil
}
// GetRetryMaxAttempts returns the value of AWS_MAX_ATTEMPTS if was specified,
// and not 0.
func (c EnvConfig) GetRetryMaxAttempts(ctx context.Context) (int, bool, error) {
if c.RetryMaxAttempts == 0 {
return 0, false, nil
}
return c.RetryMaxAttempts, true, nil
}
// GetRetryMode returns the RetryMode of AWS_RETRY_MODE if was specified, and a
// valid value.
func (c EnvConfig) GetRetryMode(ctx context.Context) (aws.RetryMode, bool, error) {
if len(c.RetryMode) == 0 {
return "", false, nil
}
return c.RetryMode, true, nil
}
func setEC2IMDSClientEnableState(state *imds.ClientEnableState, keys []string) {
for _, k := range keys {
value := os.Getenv(k)
@@ -313,6 +371,31 @@ func setEC2IMDSClientEnableState(state *imds.ClientEnableState, keys []string) {
}
}
func setDefaultsModeFromEnvVal(mode *aws.DefaultsMode, keys []string) error {
for _, k := range keys {
if value := os.Getenv(k); len(value) > 0 {
if ok := mode.SetFromString(value); !ok {
return fmt.Errorf("invalid %s value: %s", k, value)
}
break
}
}
return nil
}
func setRetryModeFromEnvVal(mode *aws.RetryMode, keys []string) (err error) {
for _, k := range keys {
if value := os.Getenv(k); len(value) > 0 {
*mode, err = aws.ParseRetryMode(value)
if err != nil {
return fmt.Errorf("invalid %s value, %w", k, err)
}
break
}
}
return nil
}
func setEC2IMDSEndpointMode(mode *imds.EndpointModeState, keys []string) error {
for _, k := range keys {
value := os.Getenv(k)
@@ -438,6 +521,21 @@ func setStringFromEnvVal(dst *string, keys []string) {
}
}
func setIntFromEnvVal(dst *int, keys []string) error {
for _, k := range keys {
if v := os.Getenv(k); len(v) > 0 {
i, err := strconv.ParseInt(v, 10, 64)
if err != nil {
return fmt.Errorf("invalid value %s=%s, %w", k, v, err)
}
*dst = int(i)
break
}
}
return nil
}
func setBoolPtrFromEnvVal(dst **bool, keys []string) error {
for _, k := range keys {
value := os.Getenv(k)

View File

@@ -3,4 +3,4 @@
package config
// goModuleVersion is the tagged release for this module
const goModuleVersion = "1.10.1"
const goModuleVersion = "1.15.10"

View File

@@ -18,7 +18,8 @@ import (
// LoadOptionsFunc is a type alias for LoadOptions functional option
type LoadOptionsFunc func(*LoadOptions) error
// LoadOptions are discrete set of options that are valid for loading the configuration
// LoadOptions are discrete set of options that are valid for loading the
// configuration
type LoadOptions struct {
// Region is the region to send requests to.
@@ -30,12 +31,36 @@ type LoadOptions struct {
// HTTPClient the SDK's API clients will use to invoke HTTP requests.
HTTPClient HTTPClient
// EndpointResolver that can be used to provide or override an endpoint for the given
// service and region Please see the `aws.EndpointResolver` documentation on usage.
// EndpointResolver that can be used to provide or override an endpoint for
// the given service and region.
//
// See the `aws.EndpointResolver` documentation on usage.
//
// Deprecated: See EndpointResolverWithOptions
EndpointResolver aws.EndpointResolver
// Retryer is a function that provides a Retryer implementation. A Retryer guides how HTTP requests should be
// retried in case of recoverable failures.
// EndpointResolverWithOptions that can be used to provide or override an
// endpoint for the given service and region.
//
// See the `aws.EndpointResolverWithOptions` documentation on usage.
EndpointResolverWithOptions aws.EndpointResolverWithOptions
// RetryMaxAttempts specifies the maximum number attempts an API client
// will call an operation that fails with a retryable error.
//
// This value will only be used if Retryer option is nil.
RetryMaxAttempts int
// RetryMode specifies the retry model the API client will be created with.
//
// This value will only be used if Retryer option is nil.
RetryMode aws.RetryMode
// Retryer is a function that provides a Retryer implementation. A Retryer
// guides how HTTP requests should be retried in case of recoverable
// failures.
//
// If not nil, RetryMaxAttempts, and RetryMode will be ignored.
Retryer func() aws.Retryer
// APIOptions provides the set of middleware mutations modify how the API
@@ -46,51 +71,63 @@ type LoadOptions struct {
// Logger writer interface to write logging messages to.
Logger logging.Logger
// ClientLogMode is used to configure the events that will be sent to the configured logger.
// This can be used to configure the logging of signing, retries, request, and responses
// of the SDK clients.
// ClientLogMode is used to configure the events that will be sent to the
// configured logger. This can be used to configure the logging of signing,
// retries, request, and responses of the SDK clients.
//
// See the ClientLogMode type documentation for the complete set of logging modes and available
// configuration.
// See the ClientLogMode type documentation for the complete set of logging
// modes and available configuration.
ClientLogMode *aws.ClientLogMode
// SharedConfigProfile is the profile to be used when loading the SharedConfig
SharedConfigProfile string
// SharedConfigFiles is the slice of custom shared config files to use when loading the SharedConfig.
// A non-default profile used within config file must have name defined with prefix 'profile '.
// eg [profile xyz] indicates a profile with name 'xyz'.
// To read more on the format of the config file, please refer the documentation at
// SharedConfigFiles is the slice of custom shared config files to use when
// loading the SharedConfig. A non-default profile used within config file
// must have name defined with prefix 'profile '. eg [profile xyz]
// indicates a profile with name 'xyz'. To read more on the format of the
// config file, please refer the documentation at
// https://docs.aws.amazon.com/credref/latest/refdocs/file-format.html#file-format-config
//
// If duplicate profiles are provided within the same, or across multiple shared config files, the next parsed
// profile will override only the properties that conflict with the previously defined profile.
// Note that if duplicate profiles are provided within the SharedCredentialsFiles and SharedConfigFiles,
// the properties defined in shared credentials file take precedence.
// If duplicate profiles are provided within the same, or across multiple
// shared config files, the next parsed profile will override only the
// properties that conflict with the previously defined profile. Note that
// if duplicate profiles are provided within the SharedCredentialsFiles and
// SharedConfigFiles, the properties defined in shared credentials file
// take precedence.
SharedConfigFiles []string
// SharedCredentialsFile is the slice of custom shared credentials files to use when loading the SharedConfig.
// The profile name used within credentials file must not prefix 'profile '.
// eg [xyz] indicates a profile with name 'xyz'. Profile declared as [profile xyz] will be ignored.
// To read more on the format of the credentials file, please refer the documentation at
// SharedCredentialsFile is the slice of custom shared credentials files to
// use when loading the SharedConfig. The profile name used within
// credentials file must not prefix 'profile '. eg [xyz] indicates a
// profile with name 'xyz'. Profile declared as [profile xyz] will be
// ignored. To read more on the format of the credentials file, please
// refer the documentation at
// https://docs.aws.amazon.com/credref/latest/refdocs/file-format.html#file-format-creds
//
// If duplicate profiles are provided with a same, or across multiple shared credentials files, the next parsed
// profile will override only properties that conflict with the previously defined profile.
// Note that if duplicate profiles are provided within the SharedCredentialsFiles and SharedConfigFiles,
// the properties defined in shared credentials file take precedence.
// If duplicate profiles are provided with a same, or across multiple
// shared credentials files, the next parsed profile will override only
// properties that conflict with the previously defined profile. Note that
// if duplicate profiles are provided within the SharedCredentialsFiles and
// SharedConfigFiles, the properties defined in shared credentials file
// take precedence.
SharedCredentialsFiles []string
// CustomCABundle is CA bundle PEM bytes reader
CustomCABundle io.Reader
// DefaultRegion is the fall back region, used if a region was not resolved from other sources
// DefaultRegion is the fall back region, used if a region was not resolved
// from other sources
DefaultRegion string
// UseEC2IMDSRegion indicates if SDK should retrieve the region
// from the EC2 Metadata service
UseEC2IMDSRegion *UseEC2IMDSRegion
// CredentialsCacheOptions is a function for setting the
// aws.CredentialsCacheOptions
CredentialsCacheOptions func(*aws.CredentialsCacheOptions)
// ProcessCredentialOptions is a function for setting
// the processcreds.Options
ProcessCredentialOptions func(*processcreds.Options)
@@ -132,10 +169,12 @@ type LoadOptions struct {
// AWS_EC2_METADATA_DISABLED=true
EC2IMDSClientEnableState imds.ClientEnableState
// Specifies the EC2 Instance Metadata Service default endpoint selection mode (IPv4 or IPv6)
// Specifies the EC2 Instance Metadata Service default endpoint selection
// mode (IPv4 or IPv6)
EC2IMDSEndpointMode imds.EndpointModeState
// Specifies the EC2 Instance Metadata Service endpoint to use. If specified it overrides EC2IMDSEndpointMode.
// Specifies the EC2 Instance Metadata Service endpoint to use. If
// specified it overrides EC2IMDSEndpointMode.
EC2IMDSEndpoint string
// Specifies that SDK clients must resolve a dual-stack endpoint for
@@ -145,6 +184,40 @@ type LoadOptions struct {
// Specifies that SDK clients must resolve a FIPS endpoint for
// services.
UseFIPSEndpoint aws.FIPSEndpointState
// Specifies the SDK configuration mode for defaults.
DefaultsModeOptions DefaultsModeOptions
}
func (o LoadOptions) getDefaultsMode(ctx context.Context) (aws.DefaultsMode, bool, error) {
if len(o.DefaultsModeOptions.Mode) == 0 {
return "", false, nil
}
return o.DefaultsModeOptions.Mode, true, nil
}
// GetRetryMaxAttempts returns the RetryMaxAttempts if specified in the
// LoadOptions and not 0.
func (o LoadOptions) GetRetryMaxAttempts(ctx context.Context) (int, bool, error) {
if o.RetryMaxAttempts == 0 {
return 0, false, nil
}
return o.RetryMaxAttempts, true, nil
}
// GetRetryMode returns the RetryMode specified in the LoadOptions.
func (o LoadOptions) GetRetryMode(ctx context.Context) (aws.RetryMode, bool, error) {
if len(o.RetryMode) == 0 {
return "", false, nil
}
return o.RetryMode, true, nil
}
func (o LoadOptions) getDefaultsModeIMDSClient(ctx context.Context) (*imds.Client, bool, error) {
if o.DefaultsModeOptions.IMDSClient == nil {
return nil, false, nil
}
return o.DefaultsModeOptions.IMDSClient, true, nil
}
// getRegion returns Region from config's LoadOptions
@@ -355,6 +428,29 @@ func WithCredentialsProvider(v aws.CredentialsProvider) LoadOptionsFunc {
}
}
// getCredentialsCacheOptionsProvider returns the wrapped function to set aws.CredentialsCacheOptions
func (o LoadOptions) getCredentialsCacheOptions(ctx context.Context) (func(*aws.CredentialsCacheOptions), bool, error) {
if o.CredentialsCacheOptions == nil {
return nil, false, nil
}
return o.CredentialsCacheOptions, true, nil
}
// WithCredentialsCacheOptions is a helper function to construct functional
// options that sets a function to modify the aws.CredentialsCacheOptions the
// aws.CredentialsCache will be configured with, if the CredentialsCache is used
// by the configuration loader.
//
// If multiple WithCredentialsCacheOptions calls are made, the last call
// overrides the previous call values.
func WithCredentialsCacheOptions(v func(*aws.CredentialsCacheOptions)) LoadOptionsFunc {
return func(o *LoadOptions) error {
o.CredentialsCacheOptions = v
return nil
}
}
// getProcessCredentialOptions returns the wrapped function to set processcreds.Options
func (o LoadOptions) getProcessCredentialOptions(ctx context.Context) (func(*processcreds.Options), bool, error) {
if o.ProcessCredentialOptions == nil {
@@ -505,6 +601,48 @@ func WithAPIOptions(v []func(*middleware.Stack) error) LoadOptionsFunc {
}
}
func (o LoadOptions) getRetryMaxAttempts(ctx context.Context) (int, bool, error) {
if o.RetryMaxAttempts == 0 {
return 0, false, nil
}
return o.RetryMaxAttempts, true, nil
}
// WithRetryMaxAttempts is a helper function to construct functional options that sets
// RetryMaxAttempts on LoadOptions. If RetryMaxAttempts is unset, the RetryMaxAttempts value is
// ignored. If multiple WithRetryMaxAttempts calls are made, the last call overrides
// the previous call values.
//
// Will be ignored of LoadOptions.Retryer or WithRetryer are used.
func WithRetryMaxAttempts(v int) LoadOptionsFunc {
return func(o *LoadOptions) error {
o.RetryMaxAttempts = v
return nil
}
}
func (o LoadOptions) getRetryMode(ctx context.Context) (aws.RetryMode, bool, error) {
if o.RetryMode == "" {
return "", false, nil
}
return o.RetryMode, true, nil
}
// WithRetryMode is a helper function to construct functional options that sets
// RetryMode on LoadOptions. If RetryMode is unset, the RetryMode value is
// ignored. If multiple WithRetryMode calls are made, the last call overrides
// the previous call values.
//
// Will be ignored of LoadOptions.Retryer or WithRetryer are used.
func WithRetryMode(v aws.RetryMode) LoadOptionsFunc {
return func(o *LoadOptions) error {
o.RetryMode = v
return nil
}
}
func (o LoadOptions) getRetryer(ctx context.Context) (func() aws.Retryer, bool, error) {
if o.Retryer == nil {
return nil, false, nil
@@ -533,9 +671,11 @@ func (o LoadOptions) getEndpointResolver(ctx context.Context) (aws.EndpointResol
}
// WithEndpointResolver is a helper function to construct functional options
// that sets endpoint resolver on LoadOptions. The EndpointResolver is set to nil,
// that sets the EndpointResolver on LoadOptions. If the EndpointResolver is set to nil,
// the EndpointResolver value is ignored. If multiple WithEndpointResolver calls
// are made, the last call overrides the previous call values.
//
// Deprecated: See WithEndpointResolverWithOptions
func WithEndpointResolver(v aws.EndpointResolver) LoadOptionsFunc {
return func(o *LoadOptions) error {
o.EndpointResolver = v
@@ -543,6 +683,25 @@ func WithEndpointResolver(v aws.EndpointResolver) LoadOptionsFunc {
}
}
func (o LoadOptions) getEndpointResolverWithOptions(ctx context.Context) (aws.EndpointResolverWithOptions, bool, error) {
if o.EndpointResolverWithOptions == nil {
return nil, false, nil
}
return o.EndpointResolverWithOptions, true, nil
}
// WithEndpointResolverWithOptions is a helper function to construct functional options
// that sets the EndpointResolverWithOptions on LoadOptions. If the EndpointResolverWithOptions is set to nil,
// the EndpointResolver value is ignored. If multiple WithEndpointResolver calls
// are made, the last call overrides the previous call values.
func WithEndpointResolverWithOptions(v aws.EndpointResolverWithOptions) LoadOptionsFunc {
return func(o *LoadOptions) error {
o.EndpointResolverWithOptions = v
return nil
}
}
func (o LoadOptions) getLogger(ctx context.Context) (logging.Logger, bool, error) {
if o.Logger == nil {
return nil, false, nil
@@ -748,3 +907,20 @@ func (o LoadOptions) GetUseFIPSEndpoint(ctx context.Context) (value aws.FIPSEndp
}
return o.UseFIPSEndpoint, true, nil
}
// WithDefaultsMode sets the SDK defaults configuration mode to the value provided.
//
// Zero or more functional options can be provided to provide configuration options for performing
// environment discovery when using aws.DefaultsModeAuto.
func WithDefaultsMode(mode aws.DefaultsMode, optFns ...func(options *DefaultsModeOptions)) LoadOptionsFunc {
do := DefaultsModeOptions{
Mode: mode,
}
for _, fn := range optFns {
fn(&do)
}
return func(options *LoadOptions) error {
options.DefaultsModeOptions = do
return nil
}
}

View File

@@ -11,6 +11,7 @@ import (
"github.com/aws/aws-sdk-go-v2/credentials/processcreds"
"github.com/aws/aws-sdk-go-v2/credentials/ssocreds"
"github.com/aws/aws-sdk-go-v2/credentials/stscreds"
"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
"github.com/aws/smithy-go/logging"
"github.com/aws/smithy-go/middleware"
)
@@ -162,6 +163,28 @@ func getCredentialsProvider(ctx context.Context, configs configs) (p aws.Credent
return
}
// credentialsCacheOptionsProvider is an interface for retrieving a function for setting
// the aws.CredentialsCacheOptions.
type credentialsCacheOptionsProvider interface {
getCredentialsCacheOptions(ctx context.Context) (func(*aws.CredentialsCacheOptions), bool, error)
}
// getCredentialsCacheOptionsProvider is an interface for retrieving a function for setting
// the aws.CredentialsCacheOptions.
func getCredentialsCacheOptionsProvider(ctx context.Context, configs configs) (
f func(*aws.CredentialsCacheOptions), found bool, err error,
) {
for _, config := range configs {
if p, ok := config.(credentialsCacheOptionsProvider); ok {
f, found, err = p.getCredentialsCacheOptions(ctx)
if err != nil || found {
break
}
}
}
return
}
// processCredentialOptions is an interface for retrieving a function for setting
// the processcreds.Options.
type processCredentialOptions interface {
@@ -336,6 +359,25 @@ func getEndpointResolver(ctx context.Context, configs configs) (f aws.EndpointRe
return
}
// endpointResolverWithOptionsProvider is an interface for retrieving an aws.EndpointResolverWithOptions from a configuration source
type endpointResolverWithOptionsProvider interface {
getEndpointResolverWithOptions(ctx context.Context) (aws.EndpointResolverWithOptions, bool, error)
}
// getEndpointResolver searches the provided config sources for a EndpointResolverFunc that can be used
// to configure the aws.Config.EndpointResolver value.
func getEndpointResolverWithOptions(ctx context.Context, configs configs) (f aws.EndpointResolverWithOptions, found bool, err error) {
for _, c := range configs {
if p, ok := c.(endpointResolverWithOptionsProvider); ok {
f, found, err = p.getEndpointResolverWithOptions(ctx)
if err != nil || found {
break
}
}
}
return
}
// loggerProvider is an interface for retrieving a logging.Logger from a configuration source.
type loggerProvider interface {
getLogger(ctx context.Context) (logging.Logger, bool, error)
@@ -423,5 +465,69 @@ func getSSOProviderOptions(ctx context.Context, configs configs) (v func(options
}
}
}
return
return v, found, err
}
type defaultsModeIMDSClientProvider interface {
getDefaultsModeIMDSClient(context.Context) (*imds.Client, bool, error)
}
func getDefaultsModeIMDSClient(ctx context.Context, configs configs) (v *imds.Client, found bool, err error) {
for _, c := range configs {
if p, ok := c.(defaultsModeIMDSClientProvider); ok {
v, found, err = p.getDefaultsModeIMDSClient(ctx)
if err != nil || found {
break
}
}
}
return v, found, err
}
type defaultsModeProvider interface {
getDefaultsMode(context.Context) (aws.DefaultsMode, bool, error)
}
func getDefaultsMode(ctx context.Context, configs configs) (v aws.DefaultsMode, found bool, err error) {
for _, c := range configs {
if p, ok := c.(defaultsModeProvider); ok {
v, found, err = p.getDefaultsMode(ctx)
if err != nil || found {
break
}
}
}
return v, found, err
}
type retryMaxAttemptsProvider interface {
GetRetryMaxAttempts(context.Context) (int, bool, error)
}
func getRetryMaxAttempts(ctx context.Context, configs configs) (v int, found bool, err error) {
for _, c := range configs {
if p, ok := c.(retryMaxAttemptsProvider); ok {
v, found, err = p.GetRetryMaxAttempts(ctx)
if err != nil || found {
break
}
}
}
return v, found, err
}
type retryModeProvider interface {
GetRetryMode(context.Context) (aws.RetryMode, bool, error)
}
func getRetryMode(ctx context.Context, configs configs) (v aws.RetryMode, found bool, err error) {
for _, c := range configs {
if p, ok := c.(retryModeProvider); ok {
v, found, err = p.GetRetryMode(ctx)
if err != nil || found {
break
}
}
}
return v, found, err
}

View File

@@ -11,6 +11,7 @@ import (
"github.com/aws/aws-sdk-go-v2/aws"
awshttp "github.com/aws/aws-sdk-go-v2/aws/transport/http"
"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
"github.com/aws/smithy-go/logging"
)
@@ -20,9 +21,15 @@ import (
// This should be used as the first resolver in the slice of resolvers when
// resolving external configuration.
func resolveDefaultAWSConfig(ctx context.Context, cfg *aws.Config, cfgs configs) error {
var sources []interface{}
for _, s := range cfgs {
sources = append(sources, s)
}
*cfg = aws.Config{
Credentials: aws.AnonymousCredentials{},
Logger: logging.NewStandardLogger(os.Stderr),
Credentials: aws.AnonymousCredentials{},
Logger: logging.NewStandardLogger(os.Stderr),
ConfigSources: sources,
}
return nil
}
@@ -166,6 +173,22 @@ func resolveEndpointResolver(ctx context.Context, cfg *aws.Config, configs confi
return nil
}
// resolveEndpointResolver extracts the first instance of a EndpointResolverFunc from the config slice
// and sets the functions result on the aws.Config.EndpointResolver
func resolveEndpointResolverWithOptions(ctx context.Context, cfg *aws.Config, configs configs) error {
endpointResolver, found, err := getEndpointResolverWithOptions(ctx, configs)
if err != nil {
return err
}
if !found {
return nil
}
cfg.EndpointResolverWithOptions = endpointResolver
return nil
}
func resolveLogger(ctx context.Context, cfg *aws.Config, configs configs) error {
logger, found, err := getLogger(ctx, configs)
if err != nil {
@@ -199,13 +222,17 @@ func resolveRetryer(ctx context.Context, cfg *aws.Config, configs configs) error
if err != nil {
return err
}
if !found {
if found {
cfg.Retryer = retryer
return nil
}
cfg.Retryer = retryer
return nil
// Only load the retry options if a custom retryer has not be specified.
if err = resolveRetryMaxAttempts(ctx, cfg, configs); err != nil {
return err
}
return resolveRetryMode(ctx, cfg, configs)
}
func resolveEC2IMDSRegion(ctx context.Context, cfg *aws.Config, configs configs) error {
@@ -225,3 +252,56 @@ func resolveEC2IMDSRegion(ctx context.Context, cfg *aws.Config, configs configs)
return nil
}
func resolveDefaultsModeOptions(ctx context.Context, cfg *aws.Config, configs configs) error {
defaultsMode, found, err := getDefaultsMode(ctx, configs)
if err != nil {
return err
}
if !found {
defaultsMode = aws.DefaultsModeLegacy
}
var environment aws.RuntimeEnvironment
if defaultsMode == aws.DefaultsModeAuto {
envConfig, _, _ := getAWSConfigSources(configs)
client, found, err := getDefaultsModeIMDSClient(ctx, configs)
if err != nil {
return err
}
if !found {
client = imds.NewFromConfig(*cfg)
}
environment, err = resolveDefaultsModeRuntimeEnvironment(ctx, envConfig, client)
if err != nil {
return err
}
}
cfg.DefaultsMode = defaultsMode
cfg.RuntimeEnvironment = environment
return nil
}
func resolveRetryMaxAttempts(ctx context.Context, cfg *aws.Config, configs configs) error {
maxAttempts, found, err := getRetryMaxAttempts(ctx, configs)
if err != nil || !found {
return err
}
cfg.RetryMaxAttempts = maxAttempts
return nil
}
func resolveRetryMode(ctx context.Context, cfg *aws.Config, configs configs) error {
retryMode, found, err := getRetryMode(ctx, configs)
if err != nil || !found {
return err
}
cfg.RetryMode = retryMode
return nil
}

View File

@@ -59,8 +59,8 @@ func resolveCredentials(ctx context.Context, cfg *aws.Config, configs configs) e
//
// Config providers used:
// * credentialsProviderProvider
func resolveCredentialProvider(ctx context.Context, cfg *aws.Config, cfgs configs) (bool, error) {
credProvider, found, err := getCredentialsProvider(ctx, cfgs)
func resolveCredentialProvider(ctx context.Context, cfg *aws.Config, configs configs) (bool, error) {
credProvider, found, err := getCredentialsProvider(ctx, configs)
if err != nil {
return false, err
}
@@ -68,7 +68,10 @@ func resolveCredentialProvider(ctx context.Context, cfg *aws.Config, cfgs config
return false, nil
}
cfg.Credentials = wrapWithCredentialsCache(credProvider)
cfg.Credentials, err = wrapWithCredentialsCache(ctx, configs, credProvider)
if err != nil {
return false, err
}
return true, nil
}
@@ -105,7 +108,10 @@ func resolveCredentialChain(ctx context.Context, cfg *aws.Config, configs config
}
// Wrap the resolved provider in a cache so the SDK will cache credentials.
cfg.Credentials = wrapWithCredentialsCache(cfg.Credentials)
cfg.Credentials, err = wrapWithCredentialsCache(ctx, configs, cfg.Credentials)
if err != nil {
return err
}
return nil
}
@@ -248,9 +254,12 @@ func resolveHTTPCredProvider(ctx context.Context, cfg *aws.Config, url, authToke
provider := endpointcreds.New(url, optFns...)
cfg.Credentials = wrapWithCredentialsCache(provider, func(options *aws.CredentialsCacheOptions) {
cfg.Credentials, err = wrapWithCredentialsCache(ctx, configs, provider, func(options *aws.CredentialsCacheOptions) {
options.ExpiryWindow = 5 * time.Minute
})
if err != nil {
return err
}
return nil
}
@@ -296,9 +305,10 @@ func resolveEC2RoleCredentials(ctx context.Context, cfg *aws.Config, configs con
provider := ec2rolecreds.New(optFns...)
cfg.Credentials = wrapWithCredentialsCache(provider, func(options *aws.CredentialsCacheOptions) {
options.ExpiryWindow = 5 * time.Minute
})
cfg.Credentials, err = wrapWithCredentialsCache(ctx, configs, provider)
if err != nil {
return err
}
return nil
}
@@ -430,12 +440,31 @@ func credsFromAssumeRole(ctx context.Context, cfg *aws.Config, sharedCfg *Shared
return nil
}
// wrapWithCredentialsCache will wrap provider with an aws.CredentialsCache with the provided options if the provider is not already a aws.CredentialsCache.
func wrapWithCredentialsCache(provider aws.CredentialsProvider, optFns ...func(options *aws.CredentialsCacheOptions)) aws.CredentialsProvider {
// wrapWithCredentialsCache will wrap provider with an aws.CredentialsCache
// with the provided options if the provider is not already a
// aws.CredentialsCache.
func wrapWithCredentialsCache(
ctx context.Context,
cfgs configs,
provider aws.CredentialsProvider,
optFns ...func(options *aws.CredentialsCacheOptions),
) (aws.CredentialsProvider, error) {
_, ok := provider.(*aws.CredentialsCache)
if ok {
return provider
return provider, nil
}
return aws.NewCredentialsCache(provider, optFns...)
credCacheOptions, found, err := getCredentialsCacheOptionsProvider(ctx, cfgs)
if err != nil {
return nil, err
}
// force allocation of a new slice if the additional options are
// needed, to prevent overwriting the passed in slice of options.
optFns = optFns[:len(optFns):len(optFns)]
if found {
optFns = append(optFns, credCacheOptions)
}
return aws.NewCredentialsCache(provider, optFns...), nil
}

View File

@@ -1,17 +1,19 @@
package config
import (
"bytes"
"context"
"errors"
"fmt"
"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
"io"
"io/ioutil"
"os"
"path/filepath"
"runtime"
"strings"
"time"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
"github.com/aws/aws-sdk-go-v2/internal/ini"
"github.com/aws/smithy-go/logging"
)
@@ -76,6 +78,14 @@ const (
s3DisableMultiRegionAccessPointsKey = `s3_disable_multiregion_access_points`
useFIPSEndpointKey = "use_fips_endpoint"
defaultsModeKey = "defaults_mode"
// Retry options
retryMaxAttemptsKey = "max_attempts"
retryModeKey = "retry_mode"
caBundleKey = "ca_bundle"
)
// defaultSharedConfigProfile allows for swapping the default profile for testing
@@ -166,12 +176,14 @@ type SharedConfig struct {
// s3_use_arn_region=true
S3UseARNRegion *bool
// Specifies the EC2 Instance Metadata Service default endpoint selection mode (IPv4 or IPv6)
// Specifies the EC2 Instance Metadata Service default endpoint selection
// mode (IPv4 or IPv6)
//
// ec2_metadata_service_endpoint_mode=IPv6
EC2IMDSEndpointMode imds.EndpointModeState
// Specifies the EC2 Instance Metadata Service endpoint to use. If specified it overrides EC2IMDSEndpointMode.
// Specifies the EC2 Instance Metadata Service endpoint to use. If
// specified it overrides EC2IMDSEndpointMode.
//
// ec2_metadata_service_endpoint=http://fd00:ec2::254
EC2IMDSEndpoint string
@@ -193,6 +205,65 @@ type SharedConfig struct {
//
// use_fips_endpoint=true
UseFIPSEndpoint aws.FIPSEndpointState
// Specifies which defaults mode should be used by services.
//
// defaults_mode=standard
DefaultsMode aws.DefaultsMode
// Specifies the maximum number attempts an API client will call an
// operation that fails with a retryable error.
//
// max_attempts=3
RetryMaxAttempts int
// Specifies the retry model the API client will be created with.
//
// retry_mode=standard
RetryMode aws.RetryMode
// Sets the path to a custom Credentials Authority (CA) Bundle PEM file
// that the SDK will use instead of the system's root CA bundle. Only use
// this if you want to configure the SDK to use a custom set of CAs.
//
// Enabling this option will attempt to merge the Transport into the SDK's
// HTTP client. If the client's Transport is not a http.Transport an error
// will be returned. If the Transport's TLS config is set this option will
// cause the SDK to overwrite the Transport's TLS config's RootCAs value.
//
// Setting a custom HTTPClient in the aws.Config options will override this
// setting. To use this option and custom HTTP client, the HTTP client
// needs to be provided when creating the config. Not the service client.
//
// ca_bundle=$HOME/my_custom_ca_bundle
CustomCABundle string
}
func (c SharedConfig) getDefaultsMode(ctx context.Context) (value aws.DefaultsMode, ok bool, err error) {
if len(c.DefaultsMode) == 0 {
return "", false, nil
}
return c.DefaultsMode, true, nil
}
// GetRetryMaxAttempts returns the maximum number of attempts an API client
// created Retryer should attempt an operation call before failing.
func (c SharedConfig) GetRetryMaxAttempts(ctx context.Context) (value int, ok bool, err error) {
if c.RetryMaxAttempts == 0 {
return 0, false, nil
}
return c.RetryMaxAttempts, true, nil
}
// GetRetryMode returns the model the API client should create its Retryer in.
func (c SharedConfig) GetRetryMode(ctx context.Context) (value aws.RetryMode, ok bool, err error) {
if len(c.RetryMode) == 0 {
return "", false, nil
}
return c.RetryMode, true, nil
}
// GetS3UseARNRegion returns if the S3 service should allow ARNs to direct the region
@@ -275,6 +346,19 @@ func (c SharedConfig) GetUseFIPSEndpoint(ctx context.Context) (value aws.FIPSEnd
return c.UseFIPSEndpoint, true, nil
}
// GetCustomCABundle returns the custom CA bundle's PEM bytes if the file was
func (c SharedConfig) getCustomCABundle(context.Context) (io.Reader, bool, error) {
if len(c.CustomCABundle) == 0 {
return nil, false, nil
}
b, err := ioutil.ReadFile(c.CustomCABundle)
if err != nil {
return nil, false, err
}
return bytes.NewReader(b), true, nil
}
// loadSharedConfigIgnoreNotExist is an alias for loadSharedConfig with the
// addition of ignoring when none of the files exist or when the profile
// is not found in any of the files.
@@ -549,12 +633,8 @@ func mergeSections(dst, src ini.Sections) error {
secretKey := srcSection.String(secretAccessKey)
if dstSection.Has(accessKeyIDKey) {
dstSection.Logs = append(dstSection.Logs,
fmt.Sprintf("For profile: %v, overriding credentials value for aws access key id, "+
"and aws secret access key, defined in %v, with values found in a duplicate profile "+
"defined at file %v. \n",
sectionName, dstSection.SourceFile[accessKeyIDKey],
srcSection.SourceFile[accessKeyIDKey]))
dstSection.Logs = append(dstSection.Logs, newMergeKeyLogMessage(sectionName, accessKeyIDKey,
dstSection.SourceFile[accessKeyIDKey], srcSection.SourceFile[accessKeyIDKey]))
}
// update access key
@@ -572,24 +652,8 @@ func mergeSections(dst, src ini.Sections) error {
dstSection.UpdateValue(secretAccessKey, v)
// update session token
if srcSection.Has(sessionTokenKey) {
sessionKey := srcSection.String(sessionTokenKey)
val, e := ini.NewStringValue(sessionKey)
if e != nil {
return fmt.Errorf("error merging session key, %w", e)
}
if dstSection.Has(sessionTokenKey) {
dstSection.Logs = append(dstSection.Logs,
fmt.Sprintf("For profile: %v, overriding %v value, defined in %v "+
"with a %v value found in a duplicate profile defined at file %v. \n",
sectionName, sessionTokenKey, dstSection.SourceFile[sessionTokenKey],
sessionTokenKey, srcSection.SourceFile[sessionTokenKey]))
}
dstSection.UpdateValue(sessionTokenKey, val)
dstSection.UpdateSourceFile(sessionTokenKey, srcSection.SourceFile[sessionTokenKey])
if err = mergeStringKey(&srcSection, &dstSection, sectionName, sessionTokenKey); err != nil {
return err
}
// update source file to reflect where the static creds came from
@@ -597,244 +661,40 @@ func mergeSections(dst, src ini.Sections) error {
dstSection.UpdateSourceFile(secretAccessKey, srcSection.SourceFile[secretAccessKey])
}
if srcSection.Has(roleArnKey) {
key := srcSection.String(roleArnKey)
val, err := ini.NewStringValue(key)
if err != nil {
return fmt.Errorf("error merging roleArnKey, %w", err)
stringKeys := []string{
roleArnKey,
sourceProfileKey,
credentialSourceKey,
externalIDKey,
mfaSerialKey,
roleSessionNameKey,
regionKey,
enableEndpointDiscoveryKey,
credentialProcessKey,
webIdentityTokenFileKey,
s3UseARNRegionKey,
s3DisableMultiRegionAccessPointsKey,
ec2MetadataServiceEndpointModeKey,
ec2MetadataServiceEndpointKey,
useDualStackEndpoint,
useFIPSEndpointKey,
defaultsModeKey,
retryModeKey,
}
for i := range stringKeys {
if err := mergeStringKey(&srcSection, &dstSection, sectionName, stringKeys[i]); err != nil {
return err
}
if dstSection.Has(roleArnKey) {
dstSection.Logs = append(dstSection.Logs,
fmt.Sprintf("For profile: %v, overriding %v value, defined in %v "+
"with a %v value found in a duplicate profile defined at file %v. \n",
sectionName, roleArnKey, dstSection.SourceFile[roleArnKey],
roleArnKey, srcSection.SourceFile[roleArnKey]))
}
dstSection.UpdateValue(roleArnKey, val)
dstSection.UpdateSourceFile(roleArnKey, srcSection.SourceFile[roleArnKey])
}
if srcSection.Has(sourceProfileKey) {
key := srcSection.String(sourceProfileKey)
val, err := ini.NewStringValue(key)
if err != nil {
return fmt.Errorf("error merging sourceProfileKey, %w", err)
}
if dstSection.Has(sourceProfileKey) {
dstSection.Logs = append(dstSection.Logs,
fmt.Sprintf("For profile: %v, overriding %v value, defined in %v "+
"with a %v value found in a duplicate profile defined at file %v. \n",
sectionName, sourceProfileKey, dstSection.SourceFile[sourceProfileKey],
sourceProfileKey, srcSection.SourceFile[sourceProfileKey]))
}
dstSection.UpdateValue(sourceProfileKey, val)
dstSection.UpdateSourceFile(sourceProfileKey, srcSection.SourceFile[sourceProfileKey])
intKeys := []string{
roleDurationSecondsKey,
retryMaxAttemptsKey,
}
if srcSection.Has(credentialSourceKey) {
key := srcSection.String(credentialSourceKey)
val, err := ini.NewStringValue(key)
if err != nil {
return fmt.Errorf("error merging credentialSourceKey, %w", err)
for i := range intKeys {
if err := mergeIntKey(&srcSection, &dstSection, sectionName, intKeys[i]); err != nil {
return err
}
if dstSection.Has(credentialSourceKey) {
dstSection.Logs = append(dstSection.Logs,
fmt.Sprintf("For profile: %v, overriding %v value, defined in %v "+
"with a %v value found in a duplicate profile defined at file %v. \n",
sectionName, credentialSourceKey, dstSection.SourceFile[credentialSourceKey],
credentialSourceKey, srcSection.SourceFile[credentialSourceKey]))
}
dstSection.UpdateValue(credentialSourceKey, val)
dstSection.UpdateSourceFile(credentialSourceKey, srcSection.SourceFile[credentialSourceKey])
}
if srcSection.Has(externalIDKey) {
key := srcSection.String(externalIDKey)
val, err := ini.NewStringValue(key)
if err != nil {
return fmt.Errorf("error merging externalIDKey, %w", err)
}
if dstSection.Has(externalIDKey) {
dstSection.Logs = append(dstSection.Logs,
fmt.Sprintf("For profile: %v, overriding %v value, defined in %v "+
"with a %v value found in a duplicate profile defined at file %v. \n",
sectionName, externalIDKey, dstSection.SourceFile[externalIDKey],
externalIDKey, srcSection.SourceFile[externalIDKey]))
}
dstSection.UpdateValue(externalIDKey, val)
dstSection.UpdateSourceFile(externalIDKey, srcSection.SourceFile[externalIDKey])
}
if srcSection.Has(mfaSerialKey) {
key := srcSection.String(mfaSerialKey)
val, err := ini.NewStringValue(key)
if err != nil {
return fmt.Errorf("error merging mfaSerialKey, %w", err)
}
if dstSection.Has(mfaSerialKey) {
dstSection.Logs = append(dstSection.Logs,
fmt.Sprintf("For profile: %v, overriding %v value, defined in %v "+
"with a %v value found in a duplicate profile defined at file %v. \n",
sectionName, mfaSerialKey, dstSection.SourceFile[mfaSerialKey],
mfaSerialKey, srcSection.SourceFile[mfaSerialKey]))
}
dstSection.UpdateValue(mfaSerialKey, val)
dstSection.UpdateSourceFile(mfaSerialKey, srcSection.SourceFile[mfaSerialKey])
}
if srcSection.Has(roleSessionNameKey) {
key := srcSection.String(roleSessionNameKey)
val, err := ini.NewStringValue(key)
if err != nil {
return fmt.Errorf("error merging roleSessionNameKey, %w", err)
}
if dstSection.Has(roleSessionNameKey) {
dstSection.Logs = append(dstSection.Logs,
fmt.Sprintf("For profile: %v, overriding %v value, defined in %v "+
"with a %v value found in a duplicate profile defined at file %v. \n",
sectionName, roleSessionNameKey, dstSection.SourceFile[roleSessionNameKey],
roleSessionNameKey, srcSection.SourceFile[roleSessionNameKey]))
}
dstSection.UpdateValue(roleSessionNameKey, val)
dstSection.UpdateSourceFile(roleSessionNameKey, srcSection.SourceFile[roleSessionNameKey])
}
// role duration seconds key update
if srcSection.Has(roleDurationSecondsKey) {
roleDurationSeconds := srcSection.Int(roleDurationSecondsKey)
v, err := ini.NewIntValue(roleDurationSeconds)
if err != nil {
return fmt.Errorf("error merging role duration seconds key, %w", err)
}
dstSection.UpdateValue(roleDurationSecondsKey, v)
dstSection.UpdateSourceFile(roleDurationSecondsKey, srcSection.SourceFile[roleDurationSecondsKey])
}
if srcSection.Has(regionKey) {
key := srcSection.String(regionKey)
val, err := ini.NewStringValue(key)
if err != nil {
return fmt.Errorf("error merging regionKey, %w", err)
}
if dstSection.Has(regionKey) {
dstSection.Logs = append(dstSection.Logs,
fmt.Sprintf("For profile: %v, overriding %v value, defined in %v "+
"with a %v value found in a duplicate profile defined at file %v. \n",
sectionName, regionKey, dstSection.SourceFile[regionKey],
regionKey, srcSection.SourceFile[regionKey]))
}
dstSection.UpdateValue(regionKey, val)
dstSection.UpdateSourceFile(regionKey, srcSection.SourceFile[regionKey])
}
if srcSection.Has(enableEndpointDiscoveryKey) {
key := srcSection.String(enableEndpointDiscoveryKey)
val, err := ini.NewStringValue(key)
if err != nil {
return fmt.Errorf("error merging enableEndpointDiscoveryKey, %w", err)
}
if dstSection.Has(enableEndpointDiscoveryKey) {
dstSection.Logs = append(dstSection.Logs,
fmt.Sprintf("For profile: %v, overriding %v value, defined in %v "+
"with a %v value found in a duplicate profile defined at file %v. \n",
sectionName, enableEndpointDiscoveryKey, dstSection.SourceFile[enableEndpointDiscoveryKey],
enableEndpointDiscoveryKey, srcSection.SourceFile[enableEndpointDiscoveryKey]))
}
dstSection.UpdateValue(enableEndpointDiscoveryKey, val)
dstSection.UpdateSourceFile(enableEndpointDiscoveryKey, srcSection.SourceFile[enableEndpointDiscoveryKey])
}
if srcSection.Has(credentialProcessKey) {
key := srcSection.String(credentialProcessKey)
val, err := ini.NewStringValue(key)
if err != nil {
return fmt.Errorf("error merging credentialProcessKey, %w", err)
}
if dstSection.Has(credentialProcessKey) {
dstSection.Logs = append(dstSection.Logs,
fmt.Sprintf("For profile: %v, overriding %v value, defined in %v "+
"with a %v value found in a duplicate profile defined at file %v. \n",
sectionName, credentialProcessKey, dstSection.SourceFile[credentialProcessKey],
credentialProcessKey, srcSection.SourceFile[credentialProcessKey]))
}
dstSection.UpdateValue(credentialProcessKey, val)
dstSection.UpdateSourceFile(credentialProcessKey, srcSection.SourceFile[credentialProcessKey])
}
if srcSection.Has(webIdentityTokenFileKey) {
key := srcSection.String(webIdentityTokenFileKey)
val, err := ini.NewStringValue(key)
if err != nil {
return fmt.Errorf("error merging webIdentityTokenFileKey, %w", err)
}
if dstSection.Has(webIdentityTokenFileKey) {
dstSection.Logs = append(dstSection.Logs,
fmt.Sprintf("For profile: %v, overriding %v value, defined in %v "+
"with a %v value found in a duplicate profile defined at file %v. \n",
sectionName, webIdentityTokenFileKey, dstSection.SourceFile[webIdentityTokenFileKey],
webIdentityTokenFileKey, srcSection.SourceFile[webIdentityTokenFileKey]))
}
dstSection.UpdateValue(webIdentityTokenFileKey, val)
dstSection.UpdateSourceFile(webIdentityTokenFileKey, srcSection.SourceFile[webIdentityTokenFileKey])
}
if srcSection.Has(s3UseARNRegionKey) {
key := srcSection.String(s3UseARNRegionKey)
val, err := ini.NewStringValue(key)
if err != nil {
return fmt.Errorf("error merging s3UseARNRegionKey, %w", err)
}
if dstSection.Has(s3UseARNRegionKey) {
dstSection.Logs = append(dstSection.Logs,
fmt.Sprintf("For profile: %v, overriding %v value, defined in %v "+
"with a %v value found in a duplicate profile defined at file %v. \n",
sectionName, s3UseARNRegionKey, dstSection.SourceFile[s3UseARNRegionKey],
s3UseARNRegionKey, srcSection.SourceFile[s3UseARNRegionKey]))
}
dstSection.UpdateValue(s3UseARNRegionKey, val)
dstSection.UpdateSourceFile(s3UseARNRegionKey, srcSection.SourceFile[s3UseARNRegionKey])
}
if srcSection.Has(s3DisableMultiRegionAccessPointsKey) {
key := srcSection.String(s3DisableMultiRegionAccessPointsKey)
val, err := ini.NewStringValue(key)
if err != nil {
return fmt.Errorf("error merging s3DisableMultiRegionAccessPointsKey, %w", err)
}
if dstSection.Has(s3DisableMultiRegionAccessPointsKey) {
dstSection.Logs = append(dstSection.Logs,
fmt.Sprintf("For profile: %v, overriding %v value, defined in %v "+
"with a %v value found in a duplicate profile defined at file %v. \n",
sectionName, s3DisableMultiRegionAccessPointsKey, dstSection.SourceFile[s3DisableMultiRegionAccessPointsKey],
s3DisableMultiRegionAccessPointsKey, srcSection.SourceFile[s3DisableMultiRegionAccessPointsKey]))
}
dstSection.UpdateValue(s3DisableMultiRegionAccessPointsKey, val)
dstSection.UpdateSourceFile(s3DisableMultiRegionAccessPointsKey, srcSection.SourceFile[s3DisableMultiRegionAccessPointsKey])
}
// set srcSection on dst srcSection
@@ -844,6 +704,51 @@ func mergeSections(dst, src ini.Sections) error {
return nil
}
func mergeStringKey(srcSection *ini.Section, dstSection *ini.Section, sectionName, key string) error {
if srcSection.Has(key) {
srcValue := srcSection.String(key)
val, err := ini.NewStringValue(srcValue)
if err != nil {
return fmt.Errorf("error merging %s, %w", key, err)
}
if dstSection.Has(key) {
dstSection.Logs = append(dstSection.Logs, newMergeKeyLogMessage(sectionName, key,
dstSection.SourceFile[key], srcSection.SourceFile[key]))
}
dstSection.UpdateValue(key, val)
dstSection.UpdateSourceFile(key, srcSection.SourceFile[key])
}
return nil
}
func mergeIntKey(srcSection *ini.Section, dstSection *ini.Section, sectionName, key string) error {
if srcSection.Has(key) {
srcValue := srcSection.Int(key)
v, err := ini.NewIntValue(srcValue)
if err != nil {
return fmt.Errorf("error merging %s, %w", key, err)
}
if dstSection.Has(key) {
dstSection.Logs = append(dstSection.Logs, newMergeKeyLogMessage(sectionName, key,
dstSection.SourceFile[key], srcSection.SourceFile[key]))
}
dstSection.UpdateValue(key, v)
dstSection.UpdateSourceFile(key, srcSection.SourceFile[key])
}
return nil
}
func newMergeKeyLogMessage(sectionName, key, dstSourceFile, srcSourceFile string) string {
return fmt.Sprintf("For profile: %v, overriding %v value, defined in %v "+
"with a %v value found in a duplicate profile defined at file %v. \n",
sectionName, key, dstSourceFile, key, srcSourceFile)
}
// Returns an error if all of the files fail to load. If at least one file is
// successfully loaded and contains the profile, no error will be returned.
func (c *SharedConfig) setFromIniSections(profiles map[string]struct{}, profile string,
@@ -991,6 +896,19 @@ func (c *SharedConfig) setFromIniSection(profile string, section ini.Section) er
updateUseDualStackEndpoint(&c.UseDualStackEndpoint, section, useDualStackEndpoint)
updateUseFIPSEndpoint(&c.UseFIPSEndpoint, section, useFIPSEndpointKey)
if err := updateDefaultsMode(&c.DefaultsMode, section, defaultsModeKey); err != nil {
return fmt.Errorf("failed to load %s from shared config, %w", defaultsModeKey, err)
}
if err := updateInt(&c.RetryMaxAttempts, section, retryMaxAttemptsKey); err != nil {
return fmt.Errorf("failed to load %s from shared config, %w", retryMaxAttemptsKey, err)
}
if err := updateRetryMode(&c.RetryMode, section, retryModeKey); err != nil {
return fmt.Errorf("failed to load %s from shared config, %w", retryModeKey, err)
}
updateString(&c.CustomCABundle, section, caBundleKey)
// Shared Credentials
creds := aws.Credentials{
AccessKeyID: section.String(accessKeyIDKey),
@@ -1006,6 +924,28 @@ func (c *SharedConfig) setFromIniSection(profile string, section ini.Section) er
return nil
}
func updateDefaultsMode(mode *aws.DefaultsMode, section ini.Section, key string) error {
if !section.Has(key) {
return nil
}
value := section.String(key)
if ok := mode.SetFromString(value); !ok {
return fmt.Errorf("invalid value: %s", value)
}
return nil
}
func updateRetryMode(mode *aws.RetryMode, section ini.Section, key string) (err error) {
if !section.Has(key) {
return nil
}
value := section.String(key)
if *mode, err = aws.ParseRetryMode(value); err != nil {
return err
}
return nil
}
func updateEC2MetadataServiceEndpointMode(endpointMode *imds.EndpointModeState, section ini.Section, key string) error {
if !section.Has(key) {
return nil
@@ -1204,12 +1144,9 @@ func (e CredentialRequiresARNError) Error() string {
}
func userHomeDir() string {
if runtime.GOOS == "windows" { // Windows
return os.Getenv("USERPROFILE")
}
// *nix
return os.Getenv("HOME")
// Ignore errors since we only care about Windows and *nix.
homedir, _ := os.UserHomeDir()
return homedir
}
func oneOrNone(bs ...bool) bool {
@@ -1236,6 +1173,24 @@ func updateString(dst *string, section ini.Section, key string) {
*dst = section.String(key)
}
// updateInt will only update the dst with the value in the section key, key
// is present in the section.
//
// Down casts the INI integer value from a int64 to an int, which could be
// different bit size depending on platform.
func updateInt(dst *int, section ini.Section, key string) error {
if !section.Has(key) {
return nil
}
if vt, _ := section.ValueType(key); vt != ini.IntegerType {
return fmt.Errorf("invalid value %s=%s, expect integer",
key, section.String(key))
}
*dst = int(section.Int(key))
return nil
}
// updateBool will only update the dst with the value in the section key, key
// is present in the section.
func updateBool(dst *bool, section ini.Section, key string) {