bash script for AWS assume-role

23.3k Views Asked by At

I am trying to assume an AWS role within a CI/CD pipeline, hence I have to write a script to change the role via a script. Below is the script to do that, and I used source <script>.sh to replace the existing AWS access & secret keys, and add the session key.

I checked that the 3 env variables are there by echoing them in the terminal.

#!/bin/bash

output="/tmp/assume-role-output.json"

aws sts assume-role --role-arn "arn:aws:iam::<account-id>:role/<rolename>" --role-session-name AWSCLI-Session > $output
AccessKeyId=$(cat $output | jq '.Credentials''.AccessKeyId')
SecretAccessKey=$(cat $output | jq '.Credentials''.SecretAccessKey')
SessionToken=$(cat $output | jq '.Credentials''.SessionToken')

export AWS_ACCESS_KEY_ID=$AccessKeyId
export AWS_SECRET_ACCESS_KEY=$SecretAccessKey
export AWS_SESSION_TOKEN=$SessionToken

However, when I tried running a simple aws command to list ECR images aws ecr list-images --registry-id <id> --repository-name <name>, it gave the following error message.

An error occurred (UnrecognizedClientException) when calling the ListImages operation: 
The security token included in the request is invalid.

I tried manually setting the AWS keys and token in the terminal, and surprisingly the ecr list command works.

export AWS_ACCESS_KEY_ID="XXX"
export AWS_SECRET_ACCESS_KEY="XXX"
export AWS_SESSION_TOKEN="XXX"

Does anyone know what is wrong with my script?

5

There are 5 best solutions below

0
On BEST ANSWER

If you use jq the way you do, your export values will contain quotation marks, e.g.

"ASIASZHPM3IXQXXOXFOY"

rather then:

ASIASZHPM3IXQXXOXFOY

To avoid this, you have to add -r flag to jq:

AccessKeyId=$(cat $output | jq -r '.Credentials''.AccessKeyId')
SecretAccessKey=$(cat $output | jq -r '.Credentials''.SecretAccessKey')
SessionToken=$(cat $output | jq -r '.Credentials''.SessionToken')
1
On

This is a one-liner without using a file..

OUT=$(aws sts assume-role --role-arn arn:aws:iam::<YOUR_ACCOUNT>:role/<YOUR_ROLENAME> --role-session-name aaa);\
export AWS_ACCESS_KEY_ID=$(echo $OUT | jq -r '.Credentials''.AccessKeyId');\
export AWS_SECRET_ACCESS_KEY=$(echo $OUT | jq -r '.Credentials''.SecretAccessKey');\
export AWS_SESSION_TOKEN=$(echo $OUT | jq -r '.Credentials''.SessionToken');

Might be useful..

Print it to use as bash export on another terminal

printf "export AWS_ACCESS_KEY_ID=\"%s\"\\n" $AWS_ACCESS_KEY_ID;\
printf "export AWS_SECRET_ACCESS_KEY=\"%s\"\\n" $AWS_SECRET_ACCESS_KEY;\
printf "export AWS_SESSION_TOKEN=\"%s\"\\n\\n\\n" $AWS_SESSION_TOKEN;

Print it to use in JSON context

Useful for launch.json on vs code

printf "\"AWS_ACCESS_KEY_ID\":\"$AWS_ACCESS_KEY_ID\",\\n";\
printf "\"AWS_SECRET_ACCESS_KEY\":\"$AWS_SECRET_ACCESS_KEY\",\\n";\
printf "\"AWS_SESSION_TOKEN\":\"$AWS_SESSION_TOKEN\"\\n";

Update

Here is the powershell version

$OUT = aws sts assume-role --role-arn arn:aws:iam::<YOUR_ACCOUNT>:role/<YOUR_ROLENAME> --role-session-name aaa

$JSON_OUT = ConvertFrom-Json "$OUT"

$ACCESS_KEY=$JSON_OUT.Credentials.AccessKeyId
$SECRET_KEY=$JSON_OUT.Credentials.SecretAccessKey
$SESSION_TOKEN=$JSON_OUT.Credentials.SessionToken
"Paste these env variables to your terminal to assume the role"
-join ("`n", '$Env:AWS_ACCESS_KEY_ID="', "$ACCESS_KEY", '"')
-join ('$Env:AWS_SECRET_ACCESS_KEY="', "$SECRET_KEY", '"')
-join ('$Env:AWS_SESSION_TOKEN="', "$SESSION_TOKEN", '"')
0
On

Single command to get the result

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

0
On

Adding the answer I needed, because I did not have jq available in the container I was using, in case it helps someone out.

You can also use cut to parse the output:

OUT=$(aws sts assume-role --role-arn "arn:aws:iam::<account-id>:role/<role-name>" --role-session-name <session-name>)
export AWS_ACCESS_KEY_ID=$(echo $OUT | cut -d '"' -f 6 )
export AWS_SECRET_ACCESS_KEY=$(echo $OUT | cut -d '"' -f 10 )
export AWS_SESSION_TOKEN=$(echo $OUT | cut -d '"' -f 14 )
0
On

Adding to @carmel's answer

Here's a function that you can add to bashrc/zshrc to set the enviroment variables automatically.

function assume-role() {
OUT=$(aws sts assume-role --role-arn $1 --role-session-name $2);\
export AWS_ACCESS_KEY_ID=$(echo $OUT | jq -r '.Credentials''.AccessKeyId');\
export AWS_SECRET_ACCESS_KEY=$(echo $OUT | jq -r '.Credentials''.SecretAccessKey');\
export AWS_SESSION_TOKEN=$(echo $OUT | jq -r '.Credentials''.SessionToken');
}

This can then be used as:

$ assume-role <role-arn> <role-session-name>