From ff66a9c36d7141d45e5d47fcf4562889fe9cd8b4 Mon Sep 17 00:00:00 2001 From: Graham Davison Date: Fri, 18 Feb 2022 19:21:01 -0800 Subject: [PATCH] Resolves profile name before trying to use it --- aws_config.go | 24 +++++++++++----- aws_config_test.go | 34 ++++++++++++++++++++++ credentials.go | 56 ++++++++++++++++++++++++++++-------- internal/config/config.go | 16 +++++++++++ v2/awsv1shim/go.mod | 1 + v2/awsv1shim/session_test.go | 39 +++++++++++++++++++++++-- 6 files changed, 149 insertions(+), 21 deletions(-) diff --git a/aws_config.go b/aws_config.go index 090947a4..9ca7cf66 100644 --- a/aws_config.go +++ b/aws_config.go @@ -19,7 +19,6 @@ import ( "github.com/aws/smithy-go/middleware" "github.com/hashicorp/aws-sdk-go-base/v2/internal/constants" "github.com/hashicorp/aws-sdk-go-base/v2/internal/endpoints" - "github.com/hashicorp/aws-sdk-go-base/v2/internal/expand" ) func GetAwsConfig(ctx context.Context, c *Config) (aws.Config, error) { @@ -169,14 +168,25 @@ func commonLoadOptions(c *Config) ([]func(*config.LoadOptions) error, error) { config.WithLogger(debugLogger{}), } - if len(c.SharedConfigFiles) > 0 { - configFiles, err := expand.FilePaths(c.SharedConfigFiles) - if err != nil { - return nil, fmt.Errorf("expanding shared config files: %w", err) - } + sharedCredentialsFiles, err := c.ResolveSharedCredentialsFiles() + if err != nil { + return nil, err + } + if len(sharedCredentialsFiles) > 0 { + loadOptions = append( + loadOptions, + config.WithSharedCredentialsFiles(sharedCredentialsFiles), + ) + } + + sharedConfigFiles, err := c.ResolveSharedConfigFiles() + if err != nil { + return nil, err + } + if len(sharedConfigFiles) > 0 { loadOptions = append( loadOptions, - config.WithSharedConfigFiles(configFiles), + config.WithSharedConfigFiles(sharedConfigFiles), ) } diff --git a/aws_config_test.go b/aws_config_test.go index fef8e36b..5813a980 100644 --- a/aws_config_test.go +++ b/aws_config_test.go @@ -824,6 +824,40 @@ source_profile = SourceSharedCredentials }, ExpectedRegion: "us-east-1", }, + { + Config: &Config{ + Region: "us-east-1", + }, + Description: "invalid profile name from envvar", + EnvironmentVariables: map[string]string{ + "AWS_PROFILE": "no-such-profile", + }, + ExpectedError: func(err error) bool { + var e config.SharedConfigProfileNotExistError + return errors.As(err, &e) + }, + SharedCredentialsFile: ` +[some-profile] +aws_access_key_id = DefaultSharedCredentialsAccessKey +aws_secret_access_key = DefaultSharedCredentialsSecretKey +`, + }, + { + Config: &Config{ + Profile: "no-such-profile", + Region: "us-east-1", + }, + Description: "invalid profile name from config", + ExpectedError: func(err error) bool { + var e config.SharedConfigProfileNotExistError + return errors.As(err, &e) + }, + SharedCredentialsFile: ` +[some-profile] +aws_access_key_id = DefaultSharedCredentialsAccessKey +aws_secret_access_key = DefaultSharedCredentialsSecretKey +`, + }, } for _, testCase := range testCases { diff --git a/credentials.go b/credentials.go index 61048af8..22fa9a43 100644 --- a/credentials.go +++ b/credentials.go @@ -10,7 +10,6 @@ import ( "github.com/aws/aws-sdk-go-v2/credentials" "github.com/aws/aws-sdk-go-v2/credentials/stscreds" "github.com/aws/aws-sdk-go-v2/service/sts/types" - "github.com/hashicorp/aws-sdk-go-base/v2/internal/expand" ) func getCredentialsProvider(ctx context.Context, c *Config) (aws.CredentialsProvider, error) { @@ -20,7 +19,6 @@ func getCredentialsProvider(ctx context.Context, c *Config) (aws.CredentialsProv } loadOptions = append( loadOptions, - config.WithSharedConfigProfile(c.Profile), // Bypass retries when validating authentication config.WithRetryer(func() aws.Retryer { return aws.NopRetryer{} @@ -29,6 +27,50 @@ func getCredentialsProvider(ctx context.Context, c *Config) (aws.CredentialsProv // is not included in the aws.Config returned to the caller config.WithEndpointResolverWithOptions(credentialsEndpointResolver(c)), ) + + envConfig, err := config.NewEnvConfig() + if err != nil { + return nil, err + } + + profile := c.Profile + if profile == "" { + profile = envConfig.SharedConfigProfile + } + + sharedCredentialsFiles, err := c.ResolveSharedCredentialsFiles() + if err != nil { + return nil, err + } + if len(sharedCredentialsFiles) == 0 { + sharedCredentialsFiles = []string{envConfig.SharedCredentialsFile} + } + + sharedConfigFiles, err := c.ResolveSharedConfigFiles() + if err != nil { + return nil, err + } + if len(sharedConfigFiles) == 0 { + sharedConfigFiles = []string{envConfig.SharedConfigFile} + } + + // The default AWS SDK authentication flow silently ignores invalid Profiles. Pre-validate that the Profile exists + // https://github.com/aws/aws-sdk-go-v2/issues/1591 + if profile != "" { + _, err := config.LoadSharedConfigProfile(ctx, profile, func(opts *config.LoadSharedConfigOptions) { + opts.CredentialsFiles = sharedCredentialsFiles + opts.ConfigFiles = sharedConfigFiles + }) + if err != nil { + return nil, err + } + loadOptions = append( + loadOptions, + config.WithSharedConfigProfile(c.Profile), + ) + + } + if c.AccessKey != "" || c.SecretKey != "" || c.Token != "" { loadOptions = append( loadOptions, @@ -41,16 +83,6 @@ func getCredentialsProvider(ctx context.Context, c *Config) (aws.CredentialsProv ), ) } - if len(c.SharedCredentialsFiles) > 0 { - credsFiles, err := expand.FilePaths(c.SharedCredentialsFiles) - if err != nil { - return nil, fmt.Errorf("expanding shared credentials files: %w", err) - } - loadOptions = append( - loadOptions, - config.WithSharedCredentialsFiles(credsFiles), - ) - } cfg, err := config.LoadDefaultConfig(ctx, loadOptions...) if err != nil { diff --git a/internal/config/config.go b/internal/config/config.go index 196be84f..79a026b7 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -63,3 +63,19 @@ func (c Config) CustomCABundleReader() (*bytes.Reader, error) { } return bytes.NewReader(bundle), nil } + +func (c Config) ResolveSharedConfigFiles() ([]string, error) { + v, err := expand.FilePaths(c.SharedConfigFiles) + if err != nil { + return []string{}, fmt.Errorf("expanding shared config files: %w", err) + } + return v, nil +} + +func (c Config) ResolveSharedCredentialsFiles() ([]string, error) { + v, err := expand.FilePaths(c.SharedCredentialsFiles) + if err != nil { + return []string{}, fmt.Errorf("expanding shared credentials files: %w", err) + } + return v, nil +} diff --git a/v2/awsv1shim/go.mod b/v2/awsv1shim/go.mod index 504ded63..8b25c6c8 100644 --- a/v2/awsv1shim/go.mod +++ b/v2/awsv1shim/go.mod @@ -3,6 +3,7 @@ module github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2 require ( github.com/aws/aws-sdk-go v1.42.52 github.com/aws/aws-sdk-go-v2 v1.13.0 + github.com/aws/aws-sdk-go-v2/config v1.13.1 github.com/aws/aws-sdk-go-v2/credentials v1.8.0 github.com/aws/aws-sdk-go-v2/service/sts v1.14.0 github.com/google/go-cmp v0.5.7 diff --git a/v2/awsv1shim/session_test.go b/v2/awsv1shim/session_test.go index c5695ad3..88754059 100644 --- a/v2/awsv1shim/session_test.go +++ b/v2/awsv1shim/session_test.go @@ -13,7 +13,8 @@ import ( "testing" "time" - "github.com/aws/aws-sdk-go-v2/aws/retry" + retryv2 "github.com/aws/aws-sdk-go-v2/aws/retry" + configv2 "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/aws/client" @@ -868,6 +869,40 @@ region = us-east-1 }, ExpectedRegion: "us-east-1", }, + { + Config: &awsbase.Config{ + Region: "us-east-1", + }, + Description: "invalid profile name from envvar", + EnvironmentVariables: map[string]string{ + "AWS_PROFILE": "no-such-profile", + }, + ExpectedError: func(err error) bool { + var e configv2.SharedConfigProfileNotExistError + return errors.As(err, &e) + }, + SharedCredentialsFile: ` +[some-profile] +aws_access_key_id = DefaultSharedCredentialsAccessKey +aws_secret_access_key = DefaultSharedCredentialsSecretKey +`, + }, + { + Config: &awsbase.Config{ + Profile: "no-such-profile", + Region: "us-east-1", + }, + Description: "invalid profile name from config", + ExpectedError: func(err error) bool { + var e configv2.SharedConfigProfileNotExistError + return errors.As(err, &e) + }, + SharedCredentialsFile: ` +[some-profile] +aws_access_key_id = DefaultSharedCredentialsAccessKey +aws_secret_access_key = DefaultSharedCredentialsSecretKey +`, + }, } for _, testCase := range testCases { @@ -1221,7 +1256,7 @@ func TestMaxAttempts(t *testing.T) { Region: "us-east-1", SecretKey: servicemocks.MockStaticSecretKey, }, - ExpectedMaxAttempts: retry.DefaultMaxAttempts, + ExpectedMaxAttempts: retryv2.DefaultMaxAttempts, }, "config": {