INTERMEDIATEAWS-CLIIAM

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.

By Tested on AWS CLI v2.17
Published May 30, 2026

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-identity

get-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 profile

Caveats

  • 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 MaxSessionDuration allows 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-number and --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 echo the credentials. Like all secrets, they end up in shell history. Pipe directly into export or read from a temp file with strict permissions.

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.

X (Twitter)LinkedIn