Assume an IAM Role from the AWS CLI
Use aws sts assume-role to swap into a cross-account IAM role and export temporary credentials into your shell session.
aws sts assume-role is the command that swaps your CLI identity into a different IAM role, often across AWS accounts. It returns temporary credentials that you export into your shell environment, after which every subsequent AWS CLI call runs as the assumed role. This is the canonical cross-account workflow.
Tested on AWS CLI v2.17.
When to Use This
- Running commands in a different AWS account from a single CI/CD principal
- Temporarily elevating to an admin role for a one-off operation
- Testing what an IAM role can actually do before deploying it
- Scripting cross-account migrations or audits
Don't use this when named profiles with role_arn configured already work (the CLI does this for you), or when you're inside an EC2/ECS/Lambda context that already has an instance role.
Code
# Assume the role and export credentials in one go
ROLE_ARN="arn:aws:iam::123456789012:role/CrossAccountAdmin"
SESSION_NAME="cli-$(whoami)-$(date +%s)"
CREDS=$(aws sts assume-role \
--role-arn "$ROLE_ARN" \
--role-session-name "$SESSION_NAME" \
--duration-seconds 3600 \
--query 'Credentials' \
--output json)
export AWS_ACCESS_KEY_ID=$(echo "$CREDS" | jq -r '.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo "$CREDS" | jq -r '.SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo "$CREDS" | jq -r '.SessionToken')
# Verify the swap worked
aws sts get-caller-identityget-caller-identity confirms you're now operating as the assumed role. The session name is what shows up in CloudTrail logs, so make it descriptive — Sue-cli-2026-05-31 is more useful than Session1.
Usage
A reusable shell function for daily use:
# Add to ~/.zshrc or ~/.bashrc
aws-assume() {
local role_arn="$1"
local session_name="${2:-cli-$(whoami)-$(date +%s)}"
if [ -z "$role_arn" ]; then
echo "Usage: aws-assume <role-arn> [session-name]"
return 1
fi
local creds
creds=$(aws sts assume-role \
--role-arn "$role_arn" \
--role-session-name "$session_name" \
--query 'Credentials' --output json)
export AWS_ACCESS_KEY_ID=$(echo "$creds" | jq -r '.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo "$creds" | jq -r '.SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo "$creds" | jq -r '.SessionToken')
echo "✓ Assumed $(aws sts get-caller-identity --query Arn --output text)"
}
aws-unassume() {
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN
echo "✓ Reverted to default profile"
}$ aws-assume arn:aws:iam::123456789012:role/CrossAccountAdmin
✓ Assumed arn:aws:sts::123456789012:assumed-role/CrossAccountAdmin/cli-rabi-1717084800
$ aws s3 ls
# now runs as the assumed role
$ aws-unassume
✓ Reverted to default profileCaveats
- The assumed credentials override your default profile until you unset them. If you forget to
aws-unassume, your next "production" command might run in the wrong account. The session name in CloudTrail is your audit trail. - Default duration is 1 hour. Max is 12 hours, but only if the role's
MaxSessionDurationallows it. Set with--duration-seconds. - The trust policy must allow your principal. The role you're assuming has a trust policy that says who can assume it. If your IAM user/role isn't listed there, you get a confusing access denied error.
- MFA-protected roles need
--serial-numberand--token-code. If the trust policy requires MFA, pass your MFA device ARN and a fresh TOTP code. - Session credentials cannot be refreshed. When they expire (after
duration-seconds), you must assume the role again. Your script won't fail gracefully — it'll just start getting access denied. - Don't
echothe credentials. Like all secrets, they end up in shell history. Pipe directly intoexportor read from a temp file with strict permissions.
Related Snippets & Reading
- Debug Which AWS Identity You're Using — confirm the assume worked
- Fetch a Secret from Secrets Manager — common cross-account use case
- aws sts assume-role reference — official docs
Frequently Asked Questions
What does aws sts assume-role return?
It returns temporary credentials: an access key, secret access key, and session token, all valid for a configurable duration (default 1 hour, max 12 hours). You export them as AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN env vars to use the assumed role for subsequent CLI calls.
Why use assume-role instead of switching profiles?
Profiles are static credentials per account. assume-role gives you temporary credentials for a specific role, often in a different account, with the permissions of that role. It's how cross-account access actually works under the hood — even profile-based switching uses STS underneath.