From 82731a51874cf22843cf86432e7de35ff2596e1b Mon Sep 17 00:00:00 2001 From: Noel Georgi Date: Mon, 3 Sep 2018 15:16:07 +0530 Subject: [PATCH 1/2] This PR does the following: - Fixes: https://github.com/99designs/aws-vault/issues/258 - Pulls in changes from: https://github.com/99designs/aws-vault/pull/259 and addressed the PR comments - Pass the region to the client Signed-off-by: Noel Georgi --- cli/login.go | 55 +++++++++++++++++++++++++++++++++-------------- vault/provider.go | 1 + 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/cli/login.go b/cli/login.go index 97e0a9267..f248325f8 100644 --- a/cli/login.go +++ b/cli/login.go @@ -7,6 +7,7 @@ import ( "log" "net/http" "net/url" + "strings" "time" "github.com/99designs/aws-vault/prompt" @@ -30,6 +31,7 @@ type LoginCommandInput struct { UseStdout bool FederationTokenDuration time.Duration AssumeRoleDuration time.Duration + Region string } func ConfigureLoginCommand(app *kingpin.Application) { @@ -72,12 +74,15 @@ func LoginCommand(app *kingpin.Application, input LoginCommandInput) { return } + profile, _ := awsConfig.Profile(input.Profile) + provider, err := vault.NewVaultProvider(input.Keyring, input.Profile, vault.VaultOptions{ AssumeRoleDuration: input.AssumeRoleDuration, MfaToken: input.MfaToken, MfaPrompt: input.MfaPrompt, NoSession: true, Config: awsConfig, + Region: profile.Region, }) if err != nil { app.Fatalf("Failed to create vault provider: %v", err) @@ -96,7 +101,7 @@ func LoginCommand(app *kingpin.Application, input LoginCommandInput) { // if AssumeRole isn't used, GetFederationToken has to be used for IAM credentials if val.SessionToken == "" { log.Printf("No session token found, calling GetFederationToken") - stsCreds, err := getFederationToken(val, input.FederationTokenDuration) + stsCreds, err := getFederationToken(val, input.FederationTokenDuration, provider.Region) if err != nil { app.Fatalf("Failed to call GetFederationToken: %v\n"+ "Login for non-assumed roles depends on permission to call sts:GetFederationToken", err) @@ -119,7 +124,9 @@ func LoginCommand(app *kingpin.Application, input LoginCommandInput) { return } - req, err := http.NewRequest("GET", "https://signin.aws.amazon.com/federation", nil) + loginURLPrefix, destination := generateLoginURL(provider.Region) + + req, err := http.NewRequest("GET", loginURLPrefix, nil) if err != nil { app.Fatalf("%v", err) return @@ -170,30 +177,24 @@ func LoginCommand(app *kingpin.Application, input LoginCommandInput) { return } - destination := "https://console.aws.amazon.com/" - if profile, _ := awsConfig.Profile(input.Profile); profile.Region != "" { - destination = fmt.Sprintf( - "https://%s.console.aws.amazon.com/console/home?region=%s", - profile.Region, profile.Region, - ) - } - - loginUrl := fmt.Sprintf( - "https://signin.aws.amazon.com/federation?Action=login&Issuer=aws-vault&Destination=%s&SigninToken=%s", + loginURL := fmt.Sprintf( + "%s?Action=login&Issuer=aws-vault&Destination=%s&SigninToken=%s", + loginURLPrefix, url.QueryEscape(destination), url.QueryEscape(signinToken), ) if input.UseStdout { - fmt.Println(loginUrl) - } else if err = open.Run(loginUrl); err != nil { + fmt.Println(loginURL) + } else if err = open.Run(loginURL); err != nil { log.Println(err) - fmt.Println(loginUrl) + fmt.Println(loginURL) } } -func getFederationToken(creds credentials.Value, d time.Duration) (*sts.Credentials, error) { +func getFederationToken(creds credentials.Value, d time.Duration, region string) (*sts.Credentials, error) { sess := session.New(&aws.Config{ + Region: aws.String(region), Credentials: credentials.NewCredentials(&credentials.StaticProvider{Value: creds}), }) client := sts.New(sess) @@ -216,3 +217,25 @@ func getFederationToken(creds credentials.Value, d time.Duration) (*sts.Credenti return resp.Credentials, nil } + +func generateLoginURL(region string) (string, string) { + loginURLPrefix := "https://signin.aws.amazon.com/federation" + destination := "https://console.aws.amazon.com/" + + if region != "" { + destinationDomain := "console.aws.amazon.com" + switch { + case strings.HasPrefix(region, "cn-"): + loginURLPrefix = "https://signin.amazonaws.cn/federation" + destinationDomain = "console.amazonaws.cn" + case strings.HasPrefix(region, "us-gov-"): + loginURLPrefix = "https://signin.amazonaws-us-gov.com/federation" + destinationDomain = "console.amazonaws-us-gov.com" + } + destination = fmt.Sprintf( + "https://%s.%s/console/home?region=%s", + region, destinationDomain, region, + ) + } + return loginURLPrefix, destination +} diff --git a/vault/provider.go b/vault/provider.go index f604e89ad..1bb4cf5e8 100644 --- a/vault/provider.go +++ b/vault/provider.go @@ -35,6 +35,7 @@ type VaultOptions struct { NoSession bool Config *Config MasterCreds *credentials.Value + Region string } func (o VaultOptions) Validate() error { From cf92f12da5a69e8b72ca271ac75c9cdf4c59c7fd Mon Sep 17 00:00:00 2001 From: Noel Georgi Date: Mon, 3 Sep 2018 15:17:37 +0530 Subject: [PATCH 2/2] Fix the go vet Signed-off-by: Noel Georgi --- cli/ls_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/ls_test.go b/cli/ls_test.go index 5b20712c3..dfb85b085 100644 --- a/cli/ls_test.go +++ b/cli/ls_test.go @@ -6,7 +6,7 @@ import ( "github.com/99designs/keyring" ) -func ExampleListCommand() { +func ExampleLsCommand() { keyringImpl = keyring.NewArrayKeyring([]keyring.Item{ {Key: "llamas", Data: []byte(`{"AccessKeyID":"ABC","SecretAccessKey":"XYZ"}`)}, })