@@ -92,13 +92,13 @@ func LoginCommand(input LoginCommandInput, f *vault.ConfigFile, keyring keyring.
92
92
}
93
93
94
94
var credsProvider aws.CredentialsProvider
95
+ var creds aws.Credentials
95
96
97
+ // Use a profile from the AWS config file
98
+ ckr := & vault.CredentialKeyring {Keyring : keyring }
96
99
if input .ProfileName == "" {
97
- // When no profile is specified, source credentials from the environment
98
- credsProvider = vault .NewEnvironmentCredentialsProvider ()
100
+ creds , err = retrieveTemporaryCredsFromEnvironment (config )
99
101
} else {
100
- // Use a profile from the AWS config file
101
- ckr := & vault.CredentialKeyring {Keyring : keyring }
102
102
if config .HasRole () || config .HasSSOStartURL () {
103
103
// If AssumeRole or sso.GetRoleCredentials isn't used, GetFederationToken has to be used for IAM credentials
104
104
credsProvider , err = vault .NewTempCredentialsProvider (config , ckr )
@@ -108,22 +108,15 @@ func LoginCommand(input LoginCommandInput, f *vault.ConfigFile, keyring keyring.
108
108
if err != nil {
109
109
return fmt .Errorf ("profile %s: %w" , input .ProfileName , err )
110
110
}
111
+ creds , err = credsProvider .Retrieve (context .TODO ())
111
112
}
112
113
113
- creds , err := credsProvider .Retrieve (context .TODO ())
114
114
if err != nil {
115
115
return fmt .Errorf ("Failed to get credentials: %w" , err )
116
116
}
117
117
if creds .AccessKeyID == "" && input .ProfileName == "" {
118
118
return fmt .Errorf ("argument 'profile' not provided, nor any AWS env vars found. Try --help" )
119
119
}
120
- if creds .SessionToken == "" {
121
- // When sourcing credentials from the environment, it's possible a session token wasn't set
122
- // Generating a sign-in link requires temporary credentials, so we return an error
123
- // NOTE: We deliberately chose to have this logic here rather than in 'EnvironmentVariablesCredentialsProvider'
124
- // to make it possible to reuse it for other commands than `aws-vault login` in the future
125
- return fmt .Errorf ("failed to retrieve a session token. Cannot generate a login URL without it" )
126
- }
127
120
128
121
jsonBytes , err := json .Marshal (map [string ]string {
129
122
"sessionId" : creds .AccessKeyID ,
@@ -191,6 +184,39 @@ func LoginCommand(input LoginCommandInput, f *vault.ConfigFile, keyring keyring.
191
184
return nil
192
185
}
193
186
187
+ // retrieveTemporaryCredsFromEnvironment contains the logic to retrieve the proper credentials
188
+ // from the environment.
189
+ // - Case 1: Temporary credentials are available - these are directly returned
190
+ // - Case 2: Non-temporary credentials are available. A call to sts:GetFederation is made, and the resulting temporary
191
+ // credentials returned
192
+ func retrieveTemporaryCredsFromEnvironment (config * vault.Config ) (aws.Credentials , error ) {
193
+ // When no profile is specified, source credentials from the environment
194
+ credsProvider := vault .NewEnvironmentCredentialsProvider ()
195
+ creds , err := credsProvider .Retrieve (context .TODO ())
196
+ if err != nil {
197
+ return aws.Credentials {}, fmt .Errorf ("unable to find credentials in your environment" )
198
+ }
199
+
200
+ // If the credentials we found in the environment aren't temporary,
201
+ // use sts:GetFederationToken to get temporary credentials
202
+ // allowing to generate a sign-in link.
203
+ // Non-temporary credentials cannot be used for this purpose
204
+ if creds .SessionToken == "" {
205
+ credsProvider , err := vault .NewFederationTokenCredentialsProviderFromCredentials (& creds , config )
206
+ if err != nil {
207
+ return aws.Credentials {}, err
208
+ }
209
+
210
+ creds , err = credsProvider .Retrieve (context .TODO ())
211
+ if err != nil {
212
+ err = fmt .Errorf ("non-temporary credentials found in your environment, and calling GetFederationToken resulted in: " + err .Error ())
213
+ return aws.Credentials {}, err
214
+ }
215
+ }
216
+
217
+ return creds , nil
218
+ }
219
+
194
220
func generateLoginURL (region string , path string ) (string , string ) {
195
221
loginURLPrefix := "https://signin.aws.amazon.com/federation"
196
222
destination := "https://console.aws.amazon.com/"
0 commit comments