97

To assume an AWS role in the CLI, I do the following command:

aws sts assume-role --role-arn arn:aws:iam::123456789123:role/myAwesomeRole --role-session-name test --region eu-central-1

This gives to me an output that follows the schema:

{
    "Credentials": {
        "AccessKeyId": "someAccessKeyId",
        "SecretAccessKey": "someSecretAccessKey",
        "SessionToken": "someSessionToken",
        "Expiration": "2020-08-04T06:52:13+00:00"
    },
    "AssumedRoleUser": {
        "AssumedRoleId": "idOfTheAssummedRole",
        "Arn": "theARNOfTheRoleIWantToAssume"
    }
}

And then I manually copy and paste the values of AccessKeyId, SecretAccessKey and SessionToken in a bunch of exports like this:

export AWS_ACCESS_KEY_ID="someAccessKeyId"                                                                                      
export AWS_SECRET_ACCESS_KEY="someSecretAccessKey"
export AWS_SESSION_TOKEN="someSessionToken"

To finally assume the role.

How can I do this in one go? I mean, without that manual intervention of copying and pasting the output of the aws sts ... command on the exports.

Arcones
  • 3,954
  • 4
  • 26
  • 46

9 Answers9

187

No jq, no eval, no multiple exports - using the printf built-in (i.e. no credential leakage through /proc) and command substitution:

export $(printf "AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s AWS_SESSION_TOKEN=%s" \
$(aws sts assume-role \
--role-arn arn:aws:iam::123456789012:role/MyAssumedRole \
--role-session-name MySessionName \
--query "Credentials.[AccessKeyId,SecretAccessKey,SessionToken]" \
--output text))
Nev Stokes
  • 9,051
  • 5
  • 42
  • 44
  • 21
    IMO this should be the accepted answer. I love jq, but if there's an easy solution with no external dependencies, I like it better. – DrTeeth Jul 27 '21 at 15:26
  • 2
    If using this approach in a pipeline or script it is probably wiser not to nest so many subshells and resolve the assume-role call in a single variable assignement instruction so that the whole script can halt there in case of an auth failure. See https://unix.stackexchange.com/a/23099 – N1ngu Sep 03 '21 at 12:48
  • 2
    Nice use of the `--query` argument to replace needing to use jq! – mp3foley Jan 13 '22 at 20:28
  • Using this answer I get the following error: `usage: aws [options] [ ...] [parameters] To see help text, you can run: aws help aws help aws help Unknown options: Credentials.[AccessKeyId,SecretAccessKey,SessionToken]` Any ideas whats going on? – ilam engl Nov 23 '22 at 13:11
64

Finally, a colleague shared with me this awesome snippet that gets the work done in one go:

eval $(aws sts assume-role --role-arn arn:aws:iam::123456789123:role/myAwesomeRole --role-session-name test | jq -r '.Credentials | "export AWS_ACCESS_KEY_ID=\(.AccessKeyId)\nexport AWS_SECRET_ACCESS_KEY=\(.SecretAccessKey)\nexport AWS_SESSION_TOKEN=\(.SessionToken)\n"')

Apart from the AWS CLI, it only requires jq which is usually installed in any Linux Desktop.

Arcones
  • 3,954
  • 4
  • 26
  • 46
38

You can store an IAM Role as a profile in the AWS CLI and it will automatically assume the role for you.

Here is an example from Using an IAM role in the AWS CLI - AWS Command Line Interface:

[profile marketingadmin]
role_arn = arn:aws:iam::123456789012:role/marketingadminrole
source_profile = user1

This is saying:

  • If a user specifies --profile marketingadmin
  • Then use the credentials of profile user1
  • To call AssumeRole on the specified role

This means you can simply call a command like this and it will assume the role and use the returned credentials automatically:

aws s3 ls --profile marketingadmin
John Rotenstein
  • 241,921
  • 22
  • 380
  • 470
  • 6
    It won't work if you're already using role (e.g. after SSO): `The source profile "your_profile" must have credentials.`, so fallback to the second answer. – Putnik Aug 07 '20 at 07:52
14

Arcones's answer is good but here's a way that doesn't require jq:

eval $(aws sts assume-role \
 --role-arn arn:aws:iam::012345678901:role/TrustedThirdParty \
 --role-session-name=test \
 --query 'join(``, [`export `, `AWS_ACCESS_KEY_ID=`, 
 Credentials.AccessKeyId, ` ; export `, `AWS_SECRET_ACCESS_KEY=`,
 Credentials.SecretAccessKey, `; export `, `AWS_SESSION_TOKEN=`,
 Credentials.SessionToken])' \
 --output text)
Greg Swallow
  • 151
  • 1
  • 4
  • export accepts multiple assignment arguments: `aws sts assume-role --role-arn arn:aws:iam::012345678901:role/a --role-session-name b --query 'join(``, [\`export AWS_ACCESS_KEY_ID=\`, Credentials.AccessKeyId, \` AWS_SECRET_ACCESS_KEY=\`, Credentials.SecretAccessKey, \` AWS_SESSION_TOKEN=\`, Credentials.SessionToken])' --output text` – vdm Nov 11 '22 at 12:14
3

I have had the same problem and I managed using one of the runtimes that the CLI served me.

Once obtained the credentials I used this approach, even if not so much elegant (I used PHP runtime, but you could use what you have available in your CLI):

- export AWS_ACCESS_KEY_ID=`php -r 'echo json_decode(file_get_contents("credentials.json"))->Credentials->AccessKeyId;'`
- export AWS_SECRET_ACCESS_KEY=`php -r 'echo json_decode(file_get_contents("credentials.json"))->Credentials->SecretAccessKey;'`
- export AWS_SESSION_TOKEN=`php -r 'echo json_decode(file_get_contents("credentials.json"))->Credentials->SessionToken;'`

where credentials.json is the output of the assumed role:

aws sts assume-role --role-arn "arn-of-the-role" --role-session-name "arbitrary-session-name" > credentials.json

Obviously this is just an approach, particularly helping in case of you are automating the process. It worked to me, but I don't know if it's the best. For sure not the most linear.

letscloud
  • 85
  • 2
  • 7
1

You can use aws config with external source following the guide: Sourcing credentials with an external process. Create a shell script, for example assume-role.sh:

#!/bin/sh
aws sts --profile $2 assume-role --role-arn arn:aws:iam::123456789012:role/$1 \
                                 --role-session-name test \
                                 --query "Credentials" \
                                | jq --arg version 1 '. + {Version: $version|tonumber}'   

At ~/.aws/config config profile with shell script:

[profile desktop]
region=ap-southeast-1
output=json
    
[profile external-test]
credential_process = "/path/assume-role.sh" test desktop
    
[profile external-test2]
credential_process = "/path/assume-role.sh" test2 external-test
Abdullah Khawer
  • 4,461
  • 4
  • 29
  • 66
1
SESSION=$(aws sts assume-role \
--role-arn arn:aws:iam::123456789012:role/MyAssumedRole \
--role-session-name MySessionName \
--query "Credentials.[AccessKeyId,SecretAccessKey,SessionToken]" \
--output text)

export AWS_ACCESS_KEY_ID=$(echo $SESSION | cut -d' ' -f1)
export AWS_SECRET_ACCESS_KEY=$(echo $SESSION | cut -d' ' -f2)
export AWS_SESSION_TOKEN=$(echo $SESSION | cut -d' ' -f3)
Raman Garg
  • 91
  • 1
  • 2
0

Incase anyone wants to use credential file login:

#!/bin/bash

# Replace the variables with your own values
ROLE_ARN=<role_arn>
PROFILE=<profile_name>
REGION=<region>

# Assume the role
TEMP_CREDS=$(aws sts assume-role --role-arn "$ROLE_ARN" --role-session-name "temp-session" --output json)

# Extract the necessary information from the response
ACCESS_KEY=$(echo $TEMP_CREDS | jq -r .Credentials.AccessKeyId)
SECRET_KEY=$(echo $TEMP_CREDS | jq -r .Credentials.SecretAccessKey)
SESSION_TOKEN=$(echo $TEMP_CREDS | jq -r .Credentials.SessionToken)

# Put the information into the AWS CLI credentials file
aws configure set aws_access_key_id "$ACCESS_KEY" --profile "$PROFILE"
aws configure set aws_secret_access_key "$SECRET_KEY" --profile "$PROFILE"
aws configure set aws_session_token "$SESSION_TOKEN" --profile "$PROFILE"
aws configure set region "$REGION" --profile "$PROFILE"

# Verify the changes have been made
aws configure list --profile "$PROFILE"
Bharat Jain
  • 111
  • 1
  • 4
0

based on Nev Stokes's answer if you want to add credentials to a file

using printf

printf "
[ASSUME-ROLE]
aws_access_key_id = %s
aws_secret_access_key = %s
aws_session_token = %s
x_security_token_expires = %s" \
    $(aws sts assume-role --role-arn "arn:aws:iam::<acct#>:role/<role-name>" \
      --role-session-name <session-name> \
      --query "Credentials.[AccessKeyId,SecretAccessKey,SessionToken,Expiration]" \
      --output text) >> ~/.aws/credentials

if you prefere awk

aws sts assume-role \
--role-arn "arn:aws:iam::<acct#>:role/<role-name>" \
--role-session-name <session-name> \
--query "Credentials.[AccessKeyId,SecretAccessKey,SessionToken,Expiration]" \
--output text | awk '
BEGIN {print "[ROLE-NAME]"} 
{ print "aws_access_key_id = " $1 } 
{ print "aws_secret_access_key = " $2 } 
{ print "aws_session_token = " $3 } 
{ print "x_security_token_expires = " $4}' >> ~/.aws/credentials

to update credentials in ~/.aws/credentials file run blow sed command before running one of the above command.

sed -i -e '/ROLE-NAME/,+4d' ~/.aws/credentials