Skip to content

Commit

Permalink
[login] allow sourcing STS credentials from environment (closes #861) (
Browse files Browse the repository at this point in the history
…#864)

* [login] allow sourcing STS credentials from environment

* [login] source credentials from the environment when no profile is specified

* [login] simplify code by using built-in NewEnvFromConfig of AWS SDK
  • Loading branch information
christophetd authored Mar 7, 2022
1 parent 2a16a6f commit f8eab90
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 11 deletions.
8 changes: 8 additions & 0 deletions USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
```

### 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.
Expand Down
33 changes: 22 additions & 11 deletions cli/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ func ConfigureLoginCommand(app *kingpin.Application, a *AwsVault) {
BoolVar(&input.UseStdout)

cmd.Arg("profile", "Name of the profile").
Required().
HintAction(a.MustGetProfileNames).
StringVar(&input.ProfileName)

Expand Down Expand Up @@ -94,22 +93,34 @@ 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.ProfileName == "" {
// When no profile is specified, source credentials from the environment
credsProvider = vault.NewEnvironmentCredentialsProvider()
} 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)
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
// 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,
Expand Down
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
8 changes: 8 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down
21 changes: 21 additions & 0 deletions vault/environmentvariablescredentialsprovider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package vault

import (
"context"
"fmt"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
)

// EnvironmentVariablesCredentialsProvider retrieves AWS credentials available in the OS environment variables
type EnvironmentVariablesCredentialsProvider struct {
}

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
}
return configFromEnv.Credentials, nil
}
4 changes: 4 additions & 0 deletions vault/vault.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,10 @@ func NewFederationTokenCredentialsProvider(profileName string, k *CredentialKeyr
}, nil
}

func NewEnvironmentCredentialsProvider() aws.CredentialsProvider {
return &EnvironmentVariablesCredentialsProvider{}
}

func FindMasterCredentialsNameFor(profileName string, keyring *CredentialKeyring, config *Config) (string, error) {
hasMasterCreds, err := keyring.Has(profileName)
if err != nil {
Expand Down

0 comments on commit f8eab90

Please sign in to comment.