From d07990fc4d1bba9094483b5ed50af9da0eb3179a Mon Sep 17 00:00:00 2001 From: Christophe Tafani-Dereeper Date: Mon, 7 Mar 2022 10:48:10 +0100 Subject: [PATCH] [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) {