Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[login] allow sourcing STS credentials from environment (closes #861) #864

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 {
christophetd marked this conversation as resolved.
Show resolved Hide resolved
}

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