diff --git a/aws_config.go b/aws_config.go index 4aea2606..5849f52b 100644 --- a/aws_config.go +++ b/aws_config.go @@ -20,6 +20,8 @@ import ( "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/httpclient" + "github.com/hashicorp/go-multierror" + "github.com/mitchellh/go-homedir" ) func GetAwsConfig(ctx context.Context, c *Config) (aws.Config, error) { @@ -170,9 +172,13 @@ func commonLoadOptions(c *Config) ([]func(*config.LoadOptions) error, error) { } if len(c.SharedConfigFiles) > 0 { + configFiles, err := expandFilePaths(c.SharedConfigFiles) + if err != nil { + return nil, fmt.Errorf("error expanding shared config files: %w", err) + } loadOptions = append( loadOptions, - config.WithSharedConfigFiles(c.SharedConfigFiles), + config.WithSharedConfigFiles(configFiles), ) } @@ -216,3 +222,23 @@ func commonLoadOptions(c *Config) ([]func(*config.LoadOptions) error, error) { return loadOptions, nil } + +func expandFilePaths(in []string) ([]string, error) { + var errs *multierror.Error + result := make([]string, 0, len(in)) + for _, v := range in { + p, err := expandFilePath(v) + if err != nil { + errs = multierror.Append(errs, err) + continue + } + result = append(result, p) + } + return result, errs.ErrorOrNil() +} + +func expandFilePath(in string) (s string, err error) { + e := os.ExpandEnv(in) + s, err = homedir.Expand(e) + return +} diff --git a/aws_config_test.go b/aws_config_test.go index 04989de7..7dd76c3e 100644 --- a/aws_config_test.go +++ b/aws_config_test.go @@ -2350,3 +2350,61 @@ func (r *withNoDelay) RetryDelay(attempt int, err error) (time.Duration, error) return 0 * time.Second, nil } + +func TestExpandFilePath(t *testing.T) { + testcases := map[string]struct { + path string + expected string + envvars map[string]string + }{ + "filename": { + path: "file", + expected: "file", + }, + "file in current dir": { + path: "./file", + expected: "./file", + }, + "file with tilde": { + path: "~/file", + expected: "/my/home/dir/file", + envvars: map[string]string{ + "HOME": "/my/home/dir", + }, + }, + "file with envvar": { + path: "$HOME/file", + expected: "/home/dir/file", + envvars: map[string]string{ + "HOME": "/home/dir", + }, + }, + "full file in envvar": { + path: "$CONF_FILE", + expected: "/path/to/conf/file", + envvars: map[string]string{ + "CONF_FILE": "/path/to/conf/file", + }, + }, + } + + for name, testcase := range testcases { + t.Run(name, func(t *testing.T) { + oldEnv := servicemocks.StashEnv() + defer servicemocks.PopEnv(oldEnv) + + for k, v := range testcase.envvars { + os.Setenv(k, v) + } + + a, err := expandFilePath(testcase.path) + if err != nil { + t.Fatalf("unexpected error: %s", err) + } + + if a != testcase.expected { + t.Errorf("expected expansion to %q, got %q", testcase.expected, a) + } + }) + } +} diff --git a/credentials.go b/credentials.go index 06c33724..66ee896f 100644 --- a/credentials.go +++ b/credentials.go @@ -41,9 +41,13 @@ func getCredentialsProvider(ctx context.Context, c *Config) (aws.CredentialsProv ) } if len(c.SharedCredentialsFiles) > 0 { + credsFiles, err := expandFilePaths(c.SharedCredentialsFiles) + if err != nil { + return nil, fmt.Errorf("error expanding shared credentials files: %w", err) + } loadOptions = append( loadOptions, - config.WithSharedCredentialsFiles(c.SharedCredentialsFiles), + config.WithSharedCredentialsFiles(credsFiles), ) } diff --git a/go.mod b/go.mod index 1410a8f3..38bbf221 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/aws/smithy-go v1.10.0 github.com/google/go-cmp v0.5.7 github.com/hashicorp/go-multierror v1.1.1 + github.com/mitchellh/go-homedir v1.1.0 ) go 1.16 diff --git a/go.sum b/go.sum index f6188c52..5ea0f28c 100644 --- a/go.sum +++ b/go.sum @@ -33,6 +33,8 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= diff --git a/v2/awsv1shim/go.sum b/v2/awsv1shim/go.sum index 72b4cc3b..509fea30 100644 --- a/v2/awsv1shim/go.sum +++ b/v2/awsv1shim/go.sum @@ -38,6 +38,8 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=