Skip to main content

AWS Assume Role

This caught me by surprise at work this week, so I thought I’d make a post about it to hopefully help others avoid the same frustration. I’m very new to using AWS, so if I’m doing something horribly wrong, please let me know!

When running commands in AWS, it is common to assume a role which has permissions to perform a certain action rather than performing that action as your user. The AWS cli provides a handy command for doing so: aws sts assume-role. I ran that to assume the role I needed, ran the commands for the action I was taking, and was surprised when I got permission denied responses back. I had assumed after running aws sts assume-role, subsequent commands in the same shell would be run as the assumed role. The documentation clearly states: “Returns a set of temporary security credentials”. In hindsight, it does exactly what it says on the tin: it returns credentials; it does not use them.

The AWS cli has several methods for configuring what user/role to use for commands. You likely have a default profile and may have other named profiles in a credentials file, which you can use with the --profile argument for most commands. You can also set environment variables to override the default set in the credentials file. I’m going to use that behavior to make assume-role behave the way I want it to.

The three environment variables the AWS cli needs are AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN, which are returned in the Credentials structure of the response from assume-role. We can use the query argument to isolate the Credentials:

credentials=$(aws sts assume-role --role-arn some-role-arn --role-session-name my-session --query Credentials)

and then use jq to pull the values out into environment variables:

export AWS_ACCESS_KEY_ID=$(echo $credentials | jq -r '.AccessKeyId')

Expanding on that idea, I have the following as


credentials=$(aws sts assume-role --role-arn $ROLE_ARN --role-session-name $ROLE_SESSION_NAME --query Credentials)
export AWS_ACCESS_KEY_ID=$(echo $credentials | jq -r '.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo $credentials | jq -r '.SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo $credentials | jq -r '.SessionToken')

echo "New Identity:"
aws sts get-caller-identity

First, I unset the three environment variables in case they were previously set. If they were still set, the call to assume-role could fail if the configured user doesn’t have permission to assume the role or if they are set to temporary credentials and the session token has expired. Then it exports the three variables from the response as above and then calls aws sts get-caller-identity so I can verify the new role was set correctly. This assumes my default profile has permission to assume the role, but I haven’t needed to assume a role from a different profile yet. I’ll add the ability to do that when it comes up.

I use this like so:


Note, the script must be run with source (or .) so the variables are set in the current shell. When you’re finished running commands as the assumed role, you can unset the three environment variables to return to your default profile.