Cross-Account Access & Resource-Based Policies
~15 min read
Letting a role in one AWS account (or another AWS service) access resources in a different account, without sharing long-lived credentials.
Every IAM policy covered so far is an identity-based policy — attached to a user, group, or role, defining what THAT identity can do. A resource-based policy is attached directly to the resource itself (an S3 bucket policy, an SQS queue policy, a Lambda resource policy) and defines who is allowed to access THAT resource — including identities from a completely different AWS account. This is the mechanism that makes cross-account access possible without ever sharing a password or access key: Account A's bucket policy can explicitly grant Account B's role permission to read objects, and Account B's own IAM policies never need to mention Account A's bucket at all.
The more common pattern for cross-account access, though, is role assumption via AWS STS: instead of directly granting another account's identity permission on your resource, you create an IAM Role in your account with a trust policy naming the OTHER account (or a specific role in it) as a trusted principal. An identity in that trusted account can then call sts:AssumeRole to receive temporary credentials scoped to exactly what that role allows — no long-lived keys ever cross the account boundary, and the temporary credentials expire automatically (typically within an hour).
Both mechanisms answer the same underlying question — 'can an identity outside this account touch this resource' — but resource-based policies grant access to the resource directly, while role assumption grants a temporary, revocable identity inside your own account. A common real pattern combines both: a central security-tooling account is granted a cross-account role in every other account specifically scoped to read CloudTrail logs, letting one team audit dozens of accounts without ever holding a permanent credential in any of them.
In the AWS Console
- 1
IAM → Roles → Create role → Trusted entity type: AWS account
Create a new IAM Role, choosing 'Another AWS account' as the trusted entity type and entering the other account's 12-digit ID.
You can further restrict this to a specific role ARN in that account rather than trusting the entire account.
- 2
IAM → Roles → [new role] → Permissions
Attach the permission policies this role should grant once assumed, exactly as you would for any other role.
- 3
AWS Console → top-right account menu → Switch Role
From the trusted account, call AssumeRole (via CLI, SDK, or the console's 'Switch Role' feature) using the new role's ARN.
Switching roles in the console is the easiest way to manually verify a cross-account trust relationship works before automating it.
💻 Code example
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111122223333:role/AuditRole" },
"Action": "sts:AssumeRole"
}
]
}
💬 Deep Dive with AI
Key points
- •Resource-based policies (S3 bucket policies, SQS/Lambda resource policies) grant access directly to a resource, including from a different AWS account.
- •Cross-account role assumption (via STS AssumeRole) is the more common pattern — it issues short-lived, automatically-expiring temporary credentials, never sharing a long-lived key.
- •A role's trust policy defines WHO can assume it; its permission policies define WHAT it can do once assumed — these are two separate, distinct policy documents on the same role.
- •A common real pattern: one central account holds a cross-account auditor role, scoped to read-only access, trusted by every other account in the organization.