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_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=$(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
unset AWS_ACCESS_KEY_ID unset AWS_SECRET_ACCESS_KEY unset AWS_SESSION_TOKEN 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:
ROLE_ARN=some-role-arn ROLE_SESSION_NAME=my-session source assume_role.sh
Note, the script must be run with
.) 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.