From 2136e23356d7160f3bce8c28c34435d7d3cb3083 Mon Sep 17 00:00:00 2001 From: Christophe Tafani-Dereeper Date: Fri, 11 Feb 2022 10:42:25 +0100 Subject: [PATCH 1/3] [login] allow sourcing STS credentials from environment --- USAGE.md | 8 +++ cli/login.go | 55 ++++++++++++----- ...environmentvariablescredentialsprovider.go | 58 ++++++++++++++++++ ...onmentvariablescredentialsprovider_test.go | 61 +++++++++++++++++++ vault/vault.go | 6 ++ 5 files changed, 172 insertions(+), 16 deletions(-) create mode 100644 vault/environmentvariablescredentialsprovider.go create mode 100644 vault/environmentvariablescredentialsprovider_test.go diff --git a/USAGE.md b/USAGE.md index b936bb9c0..77d358844 100644 --- a/USAGE.md +++ b/USAGE.md @@ -304,6 +304,14 @@ You can use the `aws-vault login` command to open a browser window and login to $ aws-vault login work ``` +If you have temporary STS credentials already available in your environment, you can have aws-vault use these credentials to sign you in. +This is useful when you had to use something else than aws-vault to retrieve temporary credentials: + +```shell +# AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN must be set in your environment prior to running the below +$ aws-vault login --from-env +``` + ### Removing stored sessions If you want to remove sessions managed by `aws-vault` before they expire, you can do this with `aws-vault clear` command. diff --git a/cli/login.go b/cli/login.go index 3d1b6e65f..77b9dbda3 100644 --- a/cli/login.go +++ b/cli/login.go @@ -19,12 +19,13 @@ import ( ) type LoginCommandInput struct { - ProfileName string - UseStdout bool - Path string - Config vault.Config - SessionDuration time.Duration - NoSession bool + ProfileName string + UseStdout bool + Path string + Config vault.Config + SessionDuration time.Duration + NoSession bool + SourceCredentialsFromEnvironment bool } func ConfigureLoginCommand(app *kingpin.Application, a *AwsVault) { @@ -55,10 +56,12 @@ func ConfigureLoginCommand(app *kingpin.Application, a *AwsVault) { BoolVar(&input.UseStdout) cmd.Arg("profile", "Name of the profile"). - Required(). HintAction(a.MustGetProfileNames). StringVar(&input.ProfileName) + cmd.Flag("from-env", "Use temporary STS credentials available in the environment"). + BoolVar(&input.SourceCredentialsFromEnvironment) + cmd.Action(func(c *kingpin.ParseContext) (err error) { input.Config.MfaPromptMethod = a.PromptDriver input.Config.NonChainedGetSessionTokenDuration = input.SessionDuration @@ -82,6 +85,11 @@ func ConfigureLoginCommand(app *kingpin.Application, a *AwsVault) { func LoginCommand(input LoginCommandInput, f *vault.ConfigFile, keyring keyring.Keyring) error { vault.UseSession = !input.NoSession + // Require that either the profile name is set, either credentials should be sourced from the environment + if !input.SourceCredentialsFromEnvironment && input.ProfileName == "" { + return fmt.Errorf("required argument 'profile' not provided") + } + configLoader := vault.ConfigLoader{ File: f, BaseConfig: input.Config, @@ -94,22 +102,37 @@ func LoginCommand(input LoginCommandInput, f *vault.ConfigFile, keyring keyring. var credsProvider aws.CredentialsProvider - ckr := &vault.CredentialKeyring{Keyring: keyring} - // If AssumeRole or sso.GetRoleCredentials isn't used, GetFederationToken has to be used for IAM credentials - if config.HasRole() || config.HasSSOStartURL() { - credsProvider, err = vault.NewTempCredentialsProvider(config, ckr) + if input.SourceCredentialsFromEnvironment { + // Source credentials from environment variables + credsProvider, err = vault.NewEnvironmentCredentialsProvider() + if err != nil { + return fmt.Errorf("using credentials from environment: %w", err) + } } else { - credsProvider, err = vault.NewFederationTokenCredentialsProvider(input.ProfileName, ckr, config) - } - if err != nil { - return fmt.Errorf("profile %s: %w", input.ProfileName, err) + // Use a profile from the AWS config file + ckr := &vault.CredentialKeyring{Keyring: keyring} + if config.HasRole() || config.HasSSOStartURL() { + // If AssumeRole or sso.GetRoleCredentials isn't used, GetFederationToken has to be used for IAM credentials + credsProvider, err = vault.NewTempCredentialsProvider(config, ckr) + } else { + credsProvider, err = vault.NewFederationTokenCredentialsProvider(input.ProfileName, ckr, config) + } + if err != nil { + return fmt.Errorf("profile %s: %w", input.ProfileName, err) + } } creds, err := credsProvider.Retrieve(context.TODO()) if err != nil { return fmt.Errorf("Failed to get credentials for %s: %w", config.ProfileName, err) } - + if creds.SessionToken == "" { + // When sourcing credentials from the environment, it's possible a session token wasn't set + // Generating a sign-in link requires temporary credentials, so we return an error + // NOTE: We deliberately chose to have this logic here rather than in 'EnvironmentVariablesCredentialsProvider' + // to make it possible to reuse it for other commands than `aws-vault login` in the future + return fmt.Errorf("failed to retrieve a session token. Cannot generate a login URL without it") + } jsonBytes, err := json.Marshal(map[string]string{ "sessionId": creds.AccessKeyID, "sessionKey": creds.SecretAccessKey, diff --git a/vault/environmentvariablescredentialsprovider.go b/vault/environmentvariablescredentialsprovider.go new file mode 100644 index 000000000..f5ad33952 --- /dev/null +++ b/vault/environmentvariablescredentialsprovider.go @@ -0,0 +1,58 @@ +package vault + +import ( + "context" + "fmt" + "github.com/aws/aws-sdk-go-v2/aws" + "log" + "os" +) + +// EnvironmentVariablesCredentialsProvider retrieves AWS credentials available in the OS environment variables +type EnvironmentVariablesCredentialsProvider struct { + env EnvironmentVariablesProvider +} + +const accessKeyIdEnvKey = "AWS_ACCESS_KEY_ID" +const secretAccessKeyEnvKey = "AWS_SECRET_ACCESS_KEY" +const sessionTokenEnvKey = "AWS_SESSION_TOKEN" + +func (m *EnvironmentVariablesCredentialsProvider) Retrieve(context.Context) (creds aws.Credentials, err error) { + accessKeyId := m.env.Get(accessKeyIdEnvKey) + secretAccessKey := m.env.Get(secretAccessKeyEnvKey) + sessionToken := m.env.Get(sessionTokenEnvKey) + + if accessKeyId == "" || secretAccessKey == "" { + err := fmt.Errorf( + "missing AWS credentials in your environment.\n You need to set at least %s and %s.", + accessKeyIdEnvKey, secretAccessKeyEnvKey, + ) + return aws.Credentials{}, err + } + + if sessionToken == "" { + log.Printf("%s not found in environment variables. If using aws-vault login, "+ + "you need to specify it in your environment since generating a sign-in link requires temporary credentials", + sessionTokenEnvKey, + ) + } + + return aws.Credentials{ + AccessKeyID: accessKeyId, + SecretAccessKey: secretAccessKey, + SessionToken: sessionToken, + CanExpire: sessionToken != "", + }, nil +} + +// EnvironmentVariablesProvider is an interface to retrieve the value of environment variables +// Useful for testing +type EnvironmentVariablesProvider interface { + Get(name string) string +} + +type environmentVariablesProviderImpl struct{} + +func (m *environmentVariablesProviderImpl) Get(name string) string { + return os.Getenv(name) +} diff --git a/vault/environmentvariablescredentialsprovider_test.go b/vault/environmentvariablescredentialsprovider_test.go new file mode 100644 index 000000000..ed400ab05 --- /dev/null +++ b/vault/environmentvariablescredentialsprovider_test.go @@ -0,0 +1,61 @@ +package vault + +import ( + "context" + "github.com/aws/aws-sdk-go-v2/aws" + "reflect" + "testing" +) + +type MockEnvironment struct { + environment map[string]string +} + +func (m *MockEnvironment) Get(name string) string { + if value, ok := m.environment[name]; ok { + return value + } + return "" +} + +func TestEnvironmentVariablesCredentialsProvider_Retrieve(t *testing.T) { + tests := []struct { + name string + environment map[string]string + wantCreds aws.Credentials + wantErr bool + }{ + { + name: "no credentials in environment", + environment: map[string]string{}, + wantErr: true, + }, + { + name: "no session token in environment", + environment: map[string]string{"AWS_ACCESS_KEY_ID": "foo", "AWS_SECRET_ACCESS_KEY": "bar"}, + wantErr: false, // handled at the 'login' command level, not provider level + wantCreds: aws.Credentials{AccessKeyID: "foo", SecretAccessKey: "bar", SessionToken: "", CanExpire: false}, + }, + { + name: "all credentials in environment", + environment: map[string]string{"AWS_ACCESS_KEY_ID": "foo", "AWS_SECRET_ACCESS_KEY": "bar", "AWS_SESSION_TOKEN": "foobar"}, + wantErr: false, + wantCreds: aws.Credentials{AccessKeyID: "foo", SecretAccessKey: "bar", SessionToken: "foobar", CanExpire: true}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + m := &EnvironmentVariablesCredentialsProvider{ + env: &MockEnvironment{tt.environment}, + } + gotCreds, err := m.Retrieve(context.TODO()) + if (err != nil) != tt.wantErr { + t.Errorf("Retrieve() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(gotCreds, tt.wantCreds) { + t.Errorf("Retrieve() gotCreds = %v, want %v", gotCreds, tt.wantCreds) + } + }) + } +} diff --git a/vault/vault.go b/vault/vault.go index 057771d9a..b4a119c4a 100644 --- a/vault/vault.go +++ b/vault/vault.go @@ -291,6 +291,12 @@ func NewFederationTokenCredentialsProvider(profileName string, k *CredentialKeyr }, nil } +func NewEnvironmentCredentialsProvider() (aws.CredentialsProvider, error) { + return &EnvironmentVariablesCredentialsProvider{ + env: &environmentVariablesProviderImpl{}, + }, nil +} + func FindMasterCredentialsNameFor(profileName string, keyring *CredentialKeyring, config *Config) (string, error) { hasMasterCreds, err := keyring.Has(profileName) if err != nil { From 1c50927c01e6952647ff768641cc06c91fff60bc Mon Sep 17 00:00:00 2001 From: Christophe Tafani-Dereeper Date: Thu, 17 Feb 2022 23:24:42 +0100 Subject: [PATCH 2/3] [login] source credentials from the environment when no profile is specified --- USAGE.md | 2 +- cli/login.go | 27 +++++++------------ ...environmentvariablescredentialsprovider.go | 3 ++- 3 files changed, 12 insertions(+), 20 deletions(-) diff --git a/USAGE.md b/USAGE.md index 77d358844..5dcd71076 100644 --- a/USAGE.md +++ b/USAGE.md @@ -309,7 +309,7 @@ This is useful when you had to use something else than aws-vault to retrieve tem ```shell # AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN must be set in your environment prior to running the below -$ aws-vault login --from-env +$ aws-vault login ``` ### Removing stored sessions diff --git a/cli/login.go b/cli/login.go index 77b9dbda3..a6b7795c1 100644 --- a/cli/login.go +++ b/cli/login.go @@ -19,13 +19,12 @@ import ( ) type LoginCommandInput struct { - ProfileName string - UseStdout bool - Path string - Config vault.Config - SessionDuration time.Duration - NoSession bool - SourceCredentialsFromEnvironment bool + ProfileName string + UseStdout bool + Path string + Config vault.Config + SessionDuration time.Duration + NoSession bool } func ConfigureLoginCommand(app *kingpin.Application, a *AwsVault) { @@ -59,9 +58,6 @@ func ConfigureLoginCommand(app *kingpin.Application, a *AwsVault) { HintAction(a.MustGetProfileNames). StringVar(&input.ProfileName) - cmd.Flag("from-env", "Use temporary STS credentials available in the environment"). - BoolVar(&input.SourceCredentialsFromEnvironment) - cmd.Action(func(c *kingpin.ParseContext) (err error) { input.Config.MfaPromptMethod = a.PromptDriver input.Config.NonChainedGetSessionTokenDuration = input.SessionDuration @@ -85,11 +81,6 @@ func ConfigureLoginCommand(app *kingpin.Application, a *AwsVault) { func LoginCommand(input LoginCommandInput, f *vault.ConfigFile, keyring keyring.Keyring) error { vault.UseSession = !input.NoSession - // Require that either the profile name is set, either credentials should be sourced from the environment - if !input.SourceCredentialsFromEnvironment && input.ProfileName == "" { - return fmt.Errorf("required argument 'profile' not provided") - } - configLoader := vault.ConfigLoader{ File: f, BaseConfig: input.Config, @@ -102,8 +93,8 @@ func LoginCommand(input LoginCommandInput, f *vault.ConfigFile, keyring keyring. var credsProvider aws.CredentialsProvider - if input.SourceCredentialsFromEnvironment { - // Source credentials from environment variables + if input.ProfileName == "" { + // When no profile is specified, source credentials from the environment credsProvider, err = vault.NewEnvironmentCredentialsProvider() if err != nil { return fmt.Errorf("using credentials from environment: %w", err) @@ -124,7 +115,7 @@ func LoginCommand(input LoginCommandInput, f *vault.ConfigFile, keyring keyring. creds, err := credsProvider.Retrieve(context.TODO()) if err != nil { - return fmt.Errorf("Failed to get credentials for %s: %w", config.ProfileName, err) + return fmt.Errorf("Failed to get credentials: %w", err) } if creds.SessionToken == "" { // When sourcing credentials from the environment, it's possible a session token wasn't set diff --git a/vault/environmentvariablescredentialsprovider.go b/vault/environmentvariablescredentialsprovider.go index f5ad33952..7715dfe98 100644 --- a/vault/environmentvariablescredentialsprovider.go +++ b/vault/environmentvariablescredentialsprovider.go @@ -24,7 +24,8 @@ func (m *EnvironmentVariablesCredentialsProvider) Retrieve(context.Context) (cre if accessKeyId == "" || secretAccessKey == "" { err := fmt.Errorf( - "missing AWS credentials in your environment.\n You need to set at least %s and %s.", + "missing AWS credentials in your environment.\n You need to set at least %s and %s, "+ + "or use use aws-vault login to source credentials from your keychain", accessKeyIdEnvKey, secretAccessKeyEnvKey, ) return aws.Credentials{}, err From d07990fc4d1bba9094483b5ed50af9da0eb3179a Mon Sep 17 00:00:00 2001 From: Christophe Tafani-Dereeper Date: Mon, 7 Mar 2022 10:48:10 +0100 Subject: [PATCH 3/3] [login] simplify code by using built-in NewEnvFromConfig of AWS SDK --- cli/login.go | 5 +- go.mod | 4 ++ go.sum | 8 +++ ...environmentvariablescredentialsprovider.go | 50 ++------------- ...onmentvariablescredentialsprovider_test.go | 61 ------------------- vault/vault.go | 6 +- 6 files changed, 21 insertions(+), 113 deletions(-) delete mode 100644 vault/environmentvariablescredentialsprovider_test.go diff --git a/cli/login.go b/cli/login.go index a6b7795c1..550aca0c6 100644 --- a/cli/login.go +++ b/cli/login.go @@ -95,10 +95,7 @@ func LoginCommand(input LoginCommandInput, f *vault.ConfigFile, keyring keyring. if input.ProfileName == "" { // When no profile is specified, source credentials from the environment - credsProvider, err = vault.NewEnvironmentCredentialsProvider() - if err != nil { - return fmt.Errorf("using credentials from environment: %w", err) - } + credsProvider = vault.NewEnvironmentCredentialsProvider() } else { // Use a profile from the AWS config file ckr := &vault.CredentialKeyring{Keyring: keyring} diff --git a/go.mod b/go.mod index 4f8eac682..7a741d56c 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/99designs/keyring v1.2.0 github.com/alecthomas/kingpin v0.0.0-20200323085623-b6657d9477a6 github.com/aws/aws-sdk-go-v2 v1.14.0 + github.com/aws/aws-sdk-go-v2/config v1.14.0 github.com/aws/aws-sdk-go-v2/service/iam v1.17.0 github.com/aws/aws-sdk-go-v2/service/sso v1.10.0 github.com/aws/aws-sdk-go-v2/service/ssooidc v1.11.0 @@ -22,8 +23,11 @@ require ( github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.9.0 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.11.0 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.5 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.3.0 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.3.6 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.8.0 // indirect github.com/aws/smithy-go v1.11.0 // indirect github.com/danieljoos/wincred v1.1.2 // indirect diff --git a/go.sum b/go.sum index e135c08b9..432638248 100644 --- a/go.sum +++ b/go.sum @@ -12,10 +12,18 @@ github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAu github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/aws/aws-sdk-go-v2 v1.14.0 h1:IzSYBJHu0ZdUi27kIW6xVrs0eSxI4AzwbenzfXhhVs4= github.com/aws/aws-sdk-go-v2 v1.14.0/go.mod h1:ZA3Y8V0LrlWj63MQAnRHgKf/5QB//LSZCPNWlWrNGLU= +github.com/aws/aws-sdk-go-v2/config v1.14.0 h1:Yr8/7R6H8nqqfqgLATrcB83ax6FE2HcDXEB54XPhE98= +github.com/aws/aws-sdk-go-v2/config v1.14.0/go.mod h1:GKDRrvsq/PTaOYc9252u8Uah1hsIdtor4oIrFvUNPNM= +github.com/aws/aws-sdk-go-v2/credentials v1.9.0 h1:R3Q5s1uGLUg0aUzi+oRaUqRXhd17G/9+PiVnAwXp4sY= +github.com/aws/aws-sdk-go-v2/credentials v1.9.0/go.mod h1:PyHKqk/+tJuDY7T8R580S1j/AcSD+ODeUZ99CAUKLqQ= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.11.0 h1:CkM4d3lNeMXMZ0BDX3BtCktnKA1Ftud84Hb6d+Ix4Rk= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.11.0/go.mod h1:rwdUKJV5rm+vHu1ncD1iGDqahBEL8O0tBjVqo9eO2N0= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.5 h1:+phazLmKkjBYhFTsGYH9J7jgnA8+Aer2yE4QeS4zn6A= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.5/go.mod h1:2hXc8ooJqF2nAznsbJQIn+7h851/bu8GVC80OVTTqf8= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.3.0 h1:PO+HNeJBeRK0yVD9CQZ+VUrYfd5sXqS7YdPYHHcDkR4= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.3.0/go.mod h1:miRSv9l093jX/t/j+mBCaLqFHo9xKYzJ7DGm1BsGoJM= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.6 h1:c8s9EhIPVFMFS+R1+rtEghGrf7v83gSUWbcCYX/OPes= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.6/go.mod h1:o1ippSg3yJx5EuT4AOGXJCUcmt5vrcxla1cg6K1Q8Iw= github.com/aws/aws-sdk-go-v2/service/iam v1.17.0 h1:lG9Hx7BGOiVFTS0qJ0nM//yCxvGNxoqzfOSvo2dpsl0= github.com/aws/aws-sdk-go-v2/service/iam v1.17.0/go.mod h1:1o13iK9CH2OanAQZpbxKdhGj23ij4V8ZZ9DFnSve3fc= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.8.0 h1:JNMALY8/ZnFsfAzBHtC4gq8JeZPANmIoI2VaBgYzbf8= diff --git a/vault/environmentvariablescredentialsprovider.go b/vault/environmentvariablescredentialsprovider.go index 7715dfe98..c4f351a5b 100644 --- a/vault/environmentvariablescredentialsprovider.go +++ b/vault/environmentvariablescredentialsprovider.go @@ -4,56 +4,18 @@ import ( "context" "fmt" "github.com/aws/aws-sdk-go-v2/aws" - "log" - "os" + "github.com/aws/aws-sdk-go-v2/config" ) // EnvironmentVariablesCredentialsProvider retrieves AWS credentials available in the OS environment variables type EnvironmentVariablesCredentialsProvider struct { - env EnvironmentVariablesProvider } -const accessKeyIdEnvKey = "AWS_ACCESS_KEY_ID" -const secretAccessKeyEnvKey = "AWS_SECRET_ACCESS_KEY" -const sessionTokenEnvKey = "AWS_SESSION_TOKEN" - -func (m *EnvironmentVariablesCredentialsProvider) Retrieve(context.Context) (creds aws.Credentials, err error) { - accessKeyId := m.env.Get(accessKeyIdEnvKey) - secretAccessKey := m.env.Get(secretAccessKeyEnvKey) - sessionToken := m.env.Get(sessionTokenEnvKey) - - if accessKeyId == "" || secretAccessKey == "" { - err := fmt.Errorf( - "missing AWS credentials in your environment.\n You need to set at least %s and %s, "+ - "or use use aws-vault login to source credentials from your keychain", - accessKeyIdEnvKey, secretAccessKeyEnvKey, - ) +func (m *EnvironmentVariablesCredentialsProvider) Retrieve(context.Context) (aws.Credentials, error) { + configFromEnv, err := config.NewEnvConfig() + if err != nil { + err := fmt.Errorf("unable to authenticate to AWS through your environment variables: %w", err) return aws.Credentials{}, err } - - if sessionToken == "" { - log.Printf("%s not found in environment variables. If using aws-vault login, "+ - "you need to specify it in your environment since generating a sign-in link requires temporary credentials", - sessionTokenEnvKey, - ) - } - - return aws.Credentials{ - AccessKeyID: accessKeyId, - SecretAccessKey: secretAccessKey, - SessionToken: sessionToken, - CanExpire: sessionToken != "", - }, nil -} - -// EnvironmentVariablesProvider is an interface to retrieve the value of environment variables -// Useful for testing -type EnvironmentVariablesProvider interface { - Get(name string) string -} - -type environmentVariablesProviderImpl struct{} - -func (m *environmentVariablesProviderImpl) Get(name string) string { - return os.Getenv(name) + return configFromEnv.Credentials, nil } diff --git a/vault/environmentvariablescredentialsprovider_test.go b/vault/environmentvariablescredentialsprovider_test.go deleted file mode 100644 index ed400ab05..000000000 --- a/vault/environmentvariablescredentialsprovider_test.go +++ /dev/null @@ -1,61 +0,0 @@ -package vault - -import ( - "context" - "github.com/aws/aws-sdk-go-v2/aws" - "reflect" - "testing" -) - -type MockEnvironment struct { - environment map[string]string -} - -func (m *MockEnvironment) Get(name string) string { - if value, ok := m.environment[name]; ok { - return value - } - return "" -} - -func TestEnvironmentVariablesCredentialsProvider_Retrieve(t *testing.T) { - tests := []struct { - name string - environment map[string]string - wantCreds aws.Credentials - wantErr bool - }{ - { - name: "no credentials in environment", - environment: map[string]string{}, - wantErr: true, - }, - { - name: "no session token in environment", - environment: map[string]string{"AWS_ACCESS_KEY_ID": "foo", "AWS_SECRET_ACCESS_KEY": "bar"}, - wantErr: false, // handled at the 'login' command level, not provider level - wantCreds: aws.Credentials{AccessKeyID: "foo", SecretAccessKey: "bar", SessionToken: "", CanExpire: false}, - }, - { - name: "all credentials in environment", - environment: map[string]string{"AWS_ACCESS_KEY_ID": "foo", "AWS_SECRET_ACCESS_KEY": "bar", "AWS_SESSION_TOKEN": "foobar"}, - wantErr: false, - wantCreds: aws.Credentials{AccessKeyID: "foo", SecretAccessKey: "bar", SessionToken: "foobar", CanExpire: true}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - m := &EnvironmentVariablesCredentialsProvider{ - env: &MockEnvironment{tt.environment}, - } - gotCreds, err := m.Retrieve(context.TODO()) - if (err != nil) != tt.wantErr { - t.Errorf("Retrieve() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(gotCreds, tt.wantCreds) { - t.Errorf("Retrieve() gotCreds = %v, want %v", gotCreds, tt.wantCreds) - } - }) - } -} diff --git a/vault/vault.go b/vault/vault.go index b4a119c4a..2a5244d9a 100644 --- a/vault/vault.go +++ b/vault/vault.go @@ -291,10 +291,8 @@ func NewFederationTokenCredentialsProvider(profileName string, k *CredentialKeyr }, nil } -func NewEnvironmentCredentialsProvider() (aws.CredentialsProvider, error) { - return &EnvironmentVariablesCredentialsProvider{ - env: &environmentVariablesProviderImpl{}, - }, nil +func NewEnvironmentCredentialsProvider() aws.CredentialsProvider { + return &EnvironmentVariablesCredentialsProvider{} } func FindMasterCredentialsNameFor(profileName string, keyring *CredentialKeyring, config *Config) (string, error) {