Skip to content
Linuxbeast
Subscribe
  • Home
  • Today in Tech
  • Who is Hiring?
  • About Me
  • Work With Me
  • Lab
    • DevOps Onboarding
    • Tag Network
    • Tools
      • VPC Subnet Planner
  • Contact
Subscribe
Home › AWS › How to Set Up Cross-Account Access in AWS with AssumeRole
AWS

How to Set Up Cross-Account Access in AWS with AssumeRole

When you manage multiple AWS accounts, you often need resources in one account to access services in another — deploying code, reading S3 buckets,…

Linuxbeast Developer May 15, 2024 5 min read 660 views
How to Set Up Cross-Account Access in AWS with AssumeRole
Share:
In This Article
How AssumeRole Works› Prerequisites› Step 1: Create the Role in Account B› Step 2: Grant AssumeRole Permission in Account A›

How to Set Up Cross-Account Access in AWS with AssumeRole

March 9, 2026May 15, 2024 by Linuxbeast Developer
5 min read
660 views

When you manage multiple AWS accounts, you often need resources in one account to access services in another — deploying code, reading S3 buckets, or querying databases across accounts. Cross-account access in AWS with AssumeRole lets you do this without sharing credentials. You create a role in the target account, grant permission to assume it from the source account, and switch contexts using temporary credentials.

The examples here are run on WSL2 Ubuntu in Windows, but the AWS CLI commands work the same on any system.

Advertisement

How AssumeRole Works

The setup involves two accounts:

  • Account A (111111111111) — the account that needs access
  • Account B (222222222222) — the account that owns the resources

Account B creates an IAM role with a trust policy that says “Account A is allowed to assume this role.” Account A’s users or services then call sts:AssumeRole to get temporary credentials that work in Account B. These credentials expire automatically (default: 1 hour).

Prerequisites

  • AWS CLI v2 installed and configured
  • IAM admin access in both accounts (or enough permissions to create roles and policies)

Step 1: Create the Role in Account B

In Account B (the account with the resources), create an IAM role that Account A can assume.

Advertisement

Trust policy

Save this as trust-policy.json. It allows Account A’s root principal to assume the role:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111111111111:root"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

Using the root principal means any IAM user or role in Account A can assume this role — but only if they also have an sts:AssumeRole permission on their side (Step 2). To restrict to a specific user or role, replace root with the full ARN (e.g., arn:aws:iam::111111111111:user/deployer).

Create the role

aws iam create-role \
  --role-name CrossAccountAccessRole \
  --assume-role-policy-document file://trust-policy.json \
  --profile account-b

Attach permissions

Attach the permissions that the role needs. For example, to grant read-only S3 access:

aws iam attach-role-policy \
  --role-name CrossAccountAccessRole \
  --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess \
  --profile account-b

Use the least-privilege principle — only attach the permissions the role actually needs. You can use AWS managed policies or create a custom policy scoped to specific resources.

Step 2: Grant AssumeRole Permission in Account A

In Account A, the user or role that will assume the cross-account role needs permission to call sts:AssumeRole. Create a policy and attach it to the IAM user, group, or role:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": "arn:aws:iam::222222222222:role/CrossAccountAccessRole"
        }
    ]
}

Save this as assume-role-policy.json and attach it:

aws iam put-user-policy \
  --user-name deployer \
  --policy-name AllowCrossAccountAccess \
  --policy-document file://assume-role-policy.json \
  --profile account-a

Only sts:AssumeRole is required here. You don’t need iam:PassRole or iam:ListRoles — those are for different use cases.

Step 3: Assume the Role

There are three ways to assume the role: an AWS CLI profile (recommended for regular use), a one-time CLI command, or boto3 in Python.

Option A: AWS CLI profile (recommended)

Add a profile to ~/.aws/config that automatically assumes the role when you use it:

[profile account-b-cross]
role_arn = arn:aws:iam::222222222222:role/CrossAccountAccessRole
source_profile = account-a

Now any AWS CLI command with --profile account-b-cross assumes the role automatically:

aws s3 ls --profile account-b-cross
  • role_arn — the role in Account B to assume
  • source_profile — your Account A credentials profile, used to authenticate the AssumeRole call

The CLI handles the sts:AssumeRole call, caches the temporary credentials, and refreshes them when they expire.

Option B: Manual CLI command with environment variables

For scripts or one-off access, call sts assume-role directly and export the temporary credentials:

OUT=$(aws sts assume-role \
  --role-arn "arn:aws:iam::222222222222:role/CrossAccountAccessRole" \
  --role-session-name "cross-account-session" \
  --profile account-a)

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')
  • --role-session-name — a label for this session (shows up in CloudTrail logs)
  • Requires jq installed (sudo apt install -y jq)
  • These credentials expire after 1 hour by default

After exporting, any AWS CLI command in the same terminal session runs as Account B’s role:

aws s3 ls
aws sts get-caller-identity

To stop using the assumed role, unset the environment variables:

unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN

Option C: boto3 in Python

For Lambda functions or Python scripts that need cross-account access:

import boto3

sts_client = boto3.client('sts')
response = sts_client.assume_role(
    RoleArn='arn:aws:iam::222222222222:role/CrossAccountAccessRole',
    RoleSessionName='lambda-cross-account'
)

credentials = response['Credentials']
s3_client = boto3.client(
    's3',
    aws_access_key_id=credentials['AccessKeyId'],
    aws_secret_access_key=credentials['SecretAccessKey'],
    aws_session_token=credentials['SessionToken']
)

# Now use s3_client to interact with Account B's S3
buckets = s3_client.list_buckets()
print(buckets)

Adjusting Session Duration

By default, temporary credentials from AssumeRole expire after 1 hour. You can set a longer duration (up to 12 hours) when assuming the role:

aws sts assume-role \
  --role-arn "arn:aws:iam::222222222222:role/CrossAccountAccessRole" \
  --role-session-name "long-session" \
  --duration-seconds 3600 \
  --profile account-a

The role’s maximum session duration must also be updated to allow longer sessions. Set it when creating or updating the role:

aws iam update-role \
  --role-name CrossAccountAccessRole \
  --max-session-duration 43200 \
  --profile account-b

Valid values: 3600 (1 hour) to 43200 (12 hours).

Verifying the Setup

After assuming the role, confirm which identity you’re using:

aws sts get-caller-identity --profile account-b-cross

The output should show Account B’s account ID and the assumed role ARN:

{
    "UserId": "AROAEXAMPLEID:cross-account-session",
    "Account": "222222222222",
    "Arn": "arn:aws:sts::222222222222:assumed-role/CrossAccountAccessRole/cross-account-session"
}

Troubleshooting

Error Cause
AccessDenied when calling AssumeRole Account A’s user is missing the sts:AssumeRole permission, or Account B’s trust policy doesn’t include Account A
Not authorized to perform: iam:PassRole You’re trying to pass the role to a service (like Lambda or ECS), which requires a separate iam:PassRole permission — this is different from AssumeRole
Credentials expire too quickly Increase --duration-seconds in the assume-role call and update the role’s --max-session-duration
Wrong account in get-caller-identity Environment variables from a previous session may be overriding your profile. Run unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN

Conclusion

The setup comes down to: create a role with a trust policy in Account B, grant sts:AssumeRole in Account A, and use the CLI profile method to switch contexts automatically. For regular use, the ~/.aws/config profile approach is the cleanest — no scripts, no environment variables.

For specific cross-account use cases, see How to Copy S3 Bucket Objects Across AWS Accounts or How to Access AWS Secrets Manager from Another Account.

Advertisement

On This Page
How AssumeRole Works Prerequisites Step 1: Create the Role in Account B Trust policy Create the role Attach permissions Step 2: Grant AssumeRole Permission in Account A Step 3: Assume the Role Option A: AWS CLI profile (recommended) Option B: Manual CLI command with environment variables Option C: boto3 in Python Adjusting Session Duration Verifying the Setup Troubleshooting Conclusion

Key Takeaways

  • --role-session-name — a label for this session (shows up in CloudTrail logs)
  • Requires jq installed (sudo apt install -y jq)
  • These credentials expire after 1 hour by default

Tags

AssumeRole AWS CLI Cross-Account IAM Security STS

Level Up Your DevOps Skills

Practical guides, tutorials, and real-world best practices delivered weekly.

No spam, ever. Unsubscribe anytime.

Popular Articles

How to Mount S3 Bucket on Ubuntu with s3fs-fuse How to Mount S3 Bucket on Ubuntu 22.04 with S3FS Fuse 9.9K views How to Fix WSL CreateVm/HCS/ERROR_FILE_NOT_FOUND on Windows How to Fix WSL CreateVm/HCS/ERROR_FILE_NOT_FOUND on Windows 6.5K views How to Install and Configure Claude Code CLI on Windows PowerShell How to Install and Configure Claude Code CLI on Windows PowerShell 5.6K views How to Install Ubuntu in WSL 2 on Windows 10 and 11 How to Install Ubuntu in WSL 2 on Windows 10 and Windows 11 5.3K views How to Configure MCP Servers in VS Code, Claude Desktop, and Claude Code on WSL How to Configure MCP Servers in VS Code, Claude Desktop, and Claude Code on WSL 4.5K views
Advertisement
How to Connect Visual Studio Code with WSL 2 for Linux Ubuntu← PreviousHow to Connect Visual Studio Code with WSL 2 for Linux UbuntuNext →How to Add Swap Space on EC2 Ubuntu 22.04How to Add Swap Space on EC2 Ubuntu 22.04

Related Articles

How to Access AWS Secrets Manager from Another Account
AWS

How to Access AWS Secrets Manager from Another Account

692 views  •  Aug 16, 2024
How to Set Up CloudWatch Alarms for Amazon SES Bounce and Complaint Rates
AWS

How to Set Up CloudWatch Alarms for Amazon SES Bounce and Complaint Rates

243 views  •  Apr 27, 2026
Understanding Lambda's Event and Context Parameters in Python
AWS

Understanding Lambda’s Event and Context Parameters in Python

559 views  •  May 8, 2025
linuxbeast-logo

Built for DevOps, Cloud & Automation.

Popular Topics

  • AWS
  • WSL & Windows
  • Git
  • DevOps
  • Developer Tools
  • Programming

Resources

  • Home
  • Today in Tech
  • Who is Hiring?
  • About Me
  • Work With Me
  • Contact

Legal

  • Privacy Policy
  • Cookie Policy

Stay updated with LinuxBeast

Get the best Linux, DevOps, and Cloud content delivered to your inbox.

No spam, ever. Unsubscribe anytime.

© 2026 LinuxBeast. All rights reserved. Made with ♥ for the DevOps community.
© 2026 Linuxbeast · All rights reserved.
Manage Consent
To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.
Functional Always active
The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
Preferences
The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
Statistics
The technical storage or access that is used exclusively for statistical purposes. The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
Marketing
The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.
  • Manage options
  • Manage services
  • Manage {vendor_count} vendors
  • Read more about these purposes
View preferences
  • {title}
  • {title}
  • {title}
Esc to closeCtrl+K to open