Overview
When working with AWS IAM, you may need to configure one IAM Role to assume another IAM Role. This is a common pattern for implementing the principle of least privilege and enabling cross-account access.
Important: The configuration method differs depending on whether the two IAM Roles are in the same AWS account or in different AWS accounts.
flowchart TB
subgraph Overview[IAM Role to Role AssumeRole Overview]
direction TB
subgraph SameAccount[Same Account Scenario]
direction LR
RoleA1[Role A<br/>Source Role] -->|1. Trust Relationship<br/>on Role B| RoleB1[Role B<br/>Target Role]
RoleA1 -.->|2. Auto Permission<br/>No Policy Needed| RoleB1
end
subgraph CrossAccount[Cross-Account Scenario]
direction LR
Account1[Account 111111111111<br/>Source Account]
Account2[Account 222222222222<br/>Target Account]
RoleA2[Role A<br/>Source Role] -->|1. Trust Relationship<br/>on Role B| RoleB2[Role B<br/>Target Role]
RoleA2 -->|2. sts:AssumeRole Policy<br/>Required on Role A| RoleB2
Account1 --> RoleA2
Account2 --> RoleB2
end
end
style Overview fill:#fff,stroke:#000,stroke-width:2px
style SameAccount fill:#fff,stroke:#000,stroke-width:1px
style CrossAccount fill:#fff,stroke:#000,stroke-width:1px
style RoleA1 fill:#fff,stroke:#000,stroke-width:1px
style RoleB1 fill:#fff,stroke:#000,stroke-width:1px
style RoleA2 fill:#fff,stroke:#000,stroke-width:1px
style RoleB2 fill:#fff,stroke:#000,stroke-width:1px
style Account1 fill:#fff,stroke:#000,stroke-width:1px
style Account2 fill:#fff,stroke:#000,stroke-width:1px
Same Account: Role to Role AssumeRole
When both IAM Roles exist in the same AWS account, the configuration is straightforward.
Scenario
Let’s assume we have two IAM Roles:
- Role A: The role that will perform the AssumeRole action
- Role B: The role that will be assumed
Both roles are in the same AWS account (e.g., account 111111111111).
flowchart LR
subgraph SameAccountArch[Same Account Architecture]
direction LR
subgraph Account[Account 111111111111]
direction TB
RoleA[Role A<br/>Source Role<br/>Performs AssumeRole]
RoleB[Role B<br/>Target Role<br/>Gets Assumed]
RoleA -->|sts:AssumeRole| RoleB
end
TrustPolicy[Trust Relationship<br/>on Role B<br/>Principal: Role A]
RoleB -.->|Configure| TrustPolicy
end
style SameAccountArch fill:#fff,stroke:#000,stroke-width:2px
style Account fill:#fff,stroke:#000,stroke-width:1px
style RoleA fill:#fff,stroke:#000,stroke-width:1px
style RoleB fill:#fff,stroke:#000,stroke-width:1px
style TrustPolicy fill:#fff,stroke:#000,stroke-width:1px
Configuration
To allow Role A to assume Role B, you only need to modify the Trust Relationship (Trust Policy) of Role B.
Step 1: Update Role B’s Trust Relationship
Edit Role B’s Trust Relationship policy to include Role A as a trusted principal:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:role/Role_A"
},
"Action": "sts:AssumeRole"
}
]
}
Key Points:
- The
Principalelement specifies which IAM Role is allowed to assume this role - Use the full ARN of Role A:
arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME - The
Actionmust bests:AssumeRole
Step 2: Verify Role A Has AssumeRole Permission
In the same account scenario, Role A automatically has permission to call sts:AssumeRole on Role B once the Trust Relationship is configured. No additional policy is required on Role A.
Understanding the Principal Element
The Principal element in a Trust Relationship policy is used to specify which entities (IAM Users, IAM Roles, AWS Services, or other AWS resources) are allowed to assume the role.
For more detailed information about the Principal element, refer to the AWS IAM documentation.
Cross-Account: Role to Role AssumeRole
When the two IAM Roles are in different AWS accounts, the configuration requires an additional step.
Scenario
Let’s assume:
- Role A: Exists in AWS account
111111111111(source account) - Role B: Exists in AWS account
222222222222(target account)
Role A needs to assume Role B across accounts.
flowchart TB
subgraph CrossAccountArch[Cross-Account Architecture]
direction TB
subgraph SourceAccount[Account 111111111111<br/>Source Account]
direction TB
RoleA[Role A<br/>Source Role]
PolicyA[Permissions Policy<br/>sts:AssumeRole<br/>Resource: Role B ARN]
RoleA -.->|Requires| PolicyA
end
subgraph TargetAccount[Account 222222222222<br/>Target Account]
direction TB
RoleB[Role B<br/>Target Role]
TrustPolicy[Trust Relationship<br/>Principal: Role A ARN<br/>Action: sts:AssumeRole]
RoleB -.->|Requires| TrustPolicy
end
RoleA -->|1. Check Policy| PolicyA
PolicyA -->|2. AssumeRole Request| RoleB
RoleB -->|3. Check Trust Relationship| TrustPolicy
TrustPolicy -->|4. Grant Access| RoleB
end
style CrossAccountArch fill:#fff,stroke:#000,stroke-width:2px
style SourceAccount fill:#fff,stroke:#000,stroke-width:1px
style TargetAccount fill:#fff,stroke:#000,stroke-width:1px
style RoleA fill:#fff,stroke:#000,stroke-width:1px
style RoleB fill:#fff,stroke:#000,stroke-width:1px
style PolicyA fill:#fff,stroke:#000,stroke-width:1px
style TrustPolicy fill:#fff,stroke:#000,stroke-width:1px
Configuration
For cross-account AssumeRole, you need to configure both roles:
Step 1: Update Role B’s Trust Relationship (Target Account)
Edit Role B’s Trust Relationship policy in account 222222222222:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:role/Role_A"
},
"Action": "sts:AssumeRole"
}
]
}
Note: The Trust Relationship configuration is identical to the same-account scenario. The difference is that the ARN points to a role in a different account.
Step 2: Add AssumeRole Policy to Role A (Source Account)
This is the critical difference! Role A must have an IAM policy that explicitly allows it to assume Role B.
Add the following policy to Role A in account 111111111111:
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::222222222222:role/Role_B"
}
}
Key Points:
- The
Actionissts:AssumeRole - The
Resourcemust be the full ARN of Role B in the target account - This policy grants Role A permission to perform the AssumeRole operation
Why the Additional Policy is Required
In cross-account scenarios, AWS requires explicit permission on the source role (Role A) to assume roles in other accounts. This is a security measure to prevent unauthorized cross-account access.
Complete Example: Cross-Account Setup
Here’s a complete example showing both configurations:
flowchart TB
subgraph CompleteExample[Complete Cross-Account Example]
direction TB
subgraph SourceAcc[Account 111111111111 - Source]
direction TB
EC2Service[EC2 Service<br/>Can Assume Role A]
RoleA[Role A]
RoleATrust[Role A Trust Relationship<br/>Principal: ec2.amazonaws.com]
RoleAPolicy[Role A Permissions Policy<br/>Action: sts:AssumeRole<br/>Resource: Role B ARN]
EC2Service -->|Assumes| RoleA
RoleA -.->|Has| RoleATrust
RoleA -.->|Has| RoleAPolicy
end
subgraph TargetAcc[Account 222222222222 - Target]
direction TB
RoleB[Role B]
RoleBTrust[Role B Trust Relationship<br/>Principal: Role A ARN<br/>Action: sts:AssumeRole]
RoleBPolicy[Role B Permissions Policy<br/>Action: s3:GetObject<br/>Resource: s3://example-bucket/*]
RoleB -.->|Has| RoleBTrust
RoleB -.->|Has| RoleBPolicy
end
RoleA -->|1. AssumeRole Request| RoleB
RoleB -->|2. Access S3 Resources| S3Bucket[S3 Bucket<br/>example-bucket]
end
style CompleteExample fill:#fff,stroke:#000,stroke-width:2px
style SourceAcc fill:#fff,stroke:#000,stroke-width:1px
style TargetAcc fill:#fff,stroke:#000,stroke-width:1px
style EC2Service fill:#fff,stroke:#000,stroke-width:1px
style RoleA fill:#fff,stroke:#000,stroke-width:1px
style RoleB fill:#fff,stroke:#000,stroke-width:1px
style RoleATrust fill:#fff,stroke:#000,stroke-width:1px
style RoleAPolicy fill:#fff,stroke:#000,stroke-width:1px
style RoleBTrust fill:#fff,stroke:#000,stroke-width:1px
style RoleBPolicy fill:#fff,stroke:#000,stroke-width:1px
style S3Bucket fill:#fff,stroke:#000,stroke-width:1px
Account 111111111111 (Source Account)
Role A - Trust Relationship:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Role A - Permissions Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::222222222222:role/Role_B"
}
]
}
Account 222222222222 (Target Account)
Role B - Trust Relationship:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:role/Role_A"
},
"Action": "sts:AssumeRole"
}
]
}
Role B - Permissions Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::example-bucket/*"
}
]
}
Best Practices
-
Use External IDs for Cross-Account: Add an
ExternalIdcondition to the Trust Relationship for additional security:{ "Condition": { "StringEquals": { "sts:ExternalId": "unique-external-id-here" } } } -
Principle of Least Privilege: Grant only the minimum permissions required in the assumed role’s policy
-
Use Session Duration: Set appropriate session duration limits:
{ "Action": "sts:AssumeRole", "Condition": { "NumericLessThan": { "aws:RequestedRegion": "3600" } } } -
Monitor AssumeRole Calls: Enable CloudTrail to audit all AssumeRole operations
-
Use IAM Paths: Organize roles using IAM paths for better management:
arn:aws:iam::111111111111:role/production/app/Role_A
Conclusion
Configuring IAM Role to Role AssumeRole is a powerful feature for implementing secure, cross-account access patterns. The key difference between same-account and cross-account scenarios is:
- Same Account: Only requires Trust Relationship configuration on the target role
- Cross-Account: Requires both Trust Relationship on target role AND
sts:AssumeRolepolicy on source role
Understanding this distinction is crucial for troubleshooting access issues and implementing secure IAM architectures.
References
- AWS IAM: Allowing a Role to Assume Another Role - Original guide that helped solve this problem
- AWS IAM Principal Element Documentation - Official AWS documentation
- AWS STS AssumeRole API Reference - API documentation
- IAM Best Practices - AWS security best practices