AWS Assume Role - Complete Guide
1. Overview
AWS Assume Role is a powerful feature that allows you to temporarily assume an IAM role with specific permissions. This is essential for cross-account access, privilege escalation, and secure service-to-service communication.
graph TB
subgraph "Account A"
UserA[User/Service A]
RoleA[IAM Role A]
end
subgraph "Account B"
RoleB[IAM Role B]
ResourceB[AWS Resources]
end
UserA -->|1. Assume Role| RoleB
RoleB -->|2. Temporary Credentials| UserA
UserA -->|3. Access with Temp Creds| ResourceB
style UserA fill:#e1f5fe
style RoleB fill:#fff3e0
style ResourceB fill:#e8f5e8
Diagram Explanation: This high-level diagram shows the basic assume role flow. A user or service in Account A assumes a role in Account B, receives temporary credentials, and uses those credentials to access resources in Account B. The process involves three main steps: assumption, credential generation, and resource access.
2. Architecture Overview
graph LR
subgraph "Identity Source"
direction TB
User[User/Application]
SourceRole[Source Role/User]
end
subgraph "AWS STS"
STS[Security Token Service]
TempCreds[Temporary Credentials]
end
subgraph "Target Account"
TargetRole[Target IAM Role]
TrustPolicy[Trust Policy]
Permissions[Permission Policy]
Resources[AWS Resources]
end
User --> SourceRole
SourceRole -->|AssumeRole API| STS
STS -->|Validates| TrustPolicy
TrustPolicy -->|If Valid| STS
STS -->|Issues| TempCreds
TempCreds -->|Attached to| TargetRole
TargetRole -->|Access via| Permissions
Permissions -->|Grants Access| Resources
style STS fill:#ffeb3b
style TrustPolicy fill:#f8bbd9
style Permissions fill:#c8e6c9
Architecture Explanation: This detailed architecture shows how AWS STS (Security Token Service) acts as the intermediary. When a user or service calls the AssumeRole API, STS validates the request against the target role's trust policy. If validation passes, STS issues temporary credentials that are associated with the target role's permissions. These temporary credentials can then be used to access AWS resources according to the role's permission policies.
3. Trust Relationship Deep Dive
sequenceDiagram
participant Client as Client/User
participant STS as AWS STS
participant Role as IAM Role
participant Policy as Trust Policy
participant Resources as AWS Resources
Client->>STS: sts:AssumeRole
STS->>Policy: Check Trust Policy
Policy-->>STS: Principal Allowed?
alt Trust Policy Allows
STS->>Role: Generate Temp Credentials
Role-->>STS: Role ARN + Session Token
STS-->>Client: Temporary Credentials
Client->>Resources: Access with Temp Creds
Resources-->>Client: Resource Data
else Trust Policy Denies
STS-->>Client: Access Denied
end
Trust Relationship Explanation: This sequence diagram illustrates the trust relationship validation process. When a client requests to assume a role, STS first checks the role's trust policy to determine if the requesting principal is allowed to assume the role. Only if the trust policy permits the assumption will STS generate temporary credentials. If denied, the client receives an access denied error.
4. Setup Flow and Command Dependencies
graph TD
A[1. Create Target Role] --> B[2. Define Trust Policy]
B --> C[3. Attach Permission Policies]
C --> D[4. Configure Source Identity]
D --> E[5. Test AssumeRole]
E --> F[6. Use Temporary Credentials]
A1[aws iam create-role] --> A
B1[Trust Policy JSON] --> B
C1[aws iam attach-role-policy] --> C
D1[aws iam create-user/role] --> D
E1[aws sts assume-role] --> E
F1[aws configure set] --> F
style A fill:#ffcdd2
style B fill:#f8bbd9
style C fill:#e1bee7
style D fill:#c5cae9
style E fill:#bbdefb
style F fill:#b2dfdb
Setup Flow Explanation: This flowchart shows the logical sequence of setting up assume role functionality. Each step depends on the previous one, and the AWS CLI commands are mapped to their respective configuration steps. The process must be followed in order: create the target role, define who can assume it (trust policy), specify what the role can do (permission policies), configure the source identity, test the assumption, and finally use the temporary credentials.
5. Implementation Steps
1Create the Target IAM Role
aws iam create-role \
--role-name CrossAccountAccessRole \
--assume-role-policy-document file://trust-policy.json \
--description "Role for cross-account access"
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "unique-external-id"
},
"IpAddress": {
"aws:SourceIp": "203.0.113.0/24"
}
}
}
]
}
Trust Policy Parameters:
- Version: Policy language version (always "2012-10-17")
- Effect: "Allow" or "Deny" - controls access
- Principal: Specifies who can assume the role (AWS account, user, role, or service)
- Action: "sts:AssumeRole" - the specific action being permitted
- Condition: Additional security constraints (optional)
- sts:ExternalId: Prevents confused deputy problem
- aws:SourceIp: Restricts access to specific IP ranges
Trust Policy Purpose: This policy defines WHO can assume the role. It's the first security gate that determines if the assumption request will be processed. The trust policy is attached during role creation and can be modified later. Alternative principals include specific users, roles, or AWS services like EC2 or Lambda.
{
"Role": {
"Path": "/",
"RoleName": "CrossAccountAccessRole",
"RoleId": "AROABC123DEFGHIJKLMN",
"Arn": "arn:aws:iam::987654321098:role/CrossAccountAccessRole",
"CreateDate": "2024-01-15T10:30:00Z",
"AssumeRolePolicyDocument": "%7B%22Version%22%3A%222012-10-17%22..."
}
}
2Attach Permission Policies to the Role
aws iam attach-role-policy \
--role-name CrossAccountAccessRole \
--policy-arn arn:aws:iam::aws:policy/ReadOnlyAccess
aws iam put-role-policy \
--role-name CrossAccountAccessRole \
--policy-name CustomS3Access \
--policy-document file://permission-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my-secure-bucket",
"arn:aws:s3:::my-secure-bucket/*"
],
"Condition": {
"StringEquals": {
"s3:ExistingObjectTag/Environment": "Production"
}
}
}
]
}
Permission Policy Parameters:
- Effect: "Allow" grants permissions, "Deny" explicitly denies
- Action: Specific AWS service actions the role can perform
- Resource: AWS resources the actions can be performed on
- Condition: Additional constraints on when the policy applies
Permission Policy Purpose: This policy defines WHAT the role can do once assumed. Unlike the trust policy, this determines the actual permissions granted to the temporary credentials. You can attach multiple AWS managed policies or create custom inline policies. The principle of least privilege should be followed.
{
"ResponseMetadata": {
"RequestId": "12345678-1234-1234-1234-123456789012",
"HTTPStatusCode": 200,
"HTTPHeaders": {
"date": "Mon, 15 Jan 2024 10:35:00 GMT",
"content-type": "text/xml",
"content-length": "200"
}
}
}
3Configure Source Identity (Optional)
aws iam create-user \
--user-name AssumeRoleUser \
--path /service-accounts/
aws iam put-user-policy \
--user-name AssumeRoleUser \
--policy-name AssumeRolePolicy \
--policy-document file://assume-role-permission.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::987654321098:role/CrossAccountAccessRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "unique-external-id"
}
}
}
]
}
Source Identity Configuration:
- Resource: ARN of the specific role this user/service can assume
- sts:ExternalId: Must match the external ID in the role's trust policy
- Condition: Additional security constraints for the assumption
Source Identity Purpose: This configuration grants the source identity (user, role, or service) permission to assume the target role. This is the second security gate - the source must have permission to assume the role, AND the role must trust the source (via trust policy).
{
"User": {
"Path": "/service-accounts/",
"UserName": "AssumeRoleUser",
"UserId": "AIDABC123DEFGHIJKLMN",
"Arn": "arn:aws:iam::123456789012:user/service-accounts/AssumeRoleUser",
"CreateDate": "2024-01-15T10:40:00Z"
}
}
4Test the Assume Role Operation
aws sts assume-role \
--role-arn arn:aws:iam::987654321098:role/CrossAccountAccessRole \
--role-session-name "TestSession-$(date +%s)" \
--external-id "unique-external-id" \
--duration-seconds 3600
{
"Credentials": {
"AccessKeyId": "ASIABC123DEFGHIJKLMN",
"SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"SessionToken": "AQoDYXdzEJr......==",
"Expiration": "2024-01-15T11:40:00Z"
},
"AssumedRoleUser": {
"AssumedRoleId": "AROABC123DEFGHIJKLMN:TestSession-1705317600",
"Arn": "arn:aws:sts::987654321098:assumed-role/CrossAccountAccessRole/TestSession-1705317600"
}
}
AssumeRole Parameters:
- --role-arn: The ARN of the role to assume
- --role-session-name: A unique identifier for the session (required)
- --external-id: Must match the trust policy's external ID condition
- --duration-seconds: How long the credentials are valid (900-43200 seconds)
- --policy: Optional inline policy to further restrict permissions
- --policy-arns: Optional managed policies to restrict permissions
AssumeRole Response: The response contains temporary credentials (AccessKeyId, SecretAccessKey, SessionToken) and metadata about the assumed role session. These credentials are time-limited and must be refreshed before expiration. The AssumedRoleUser shows the unique identity for this session.
5Use the Temporary Credentials
# Method 1: Export as environment variables
export AWS_ACCESS_KEY_ID="ASIABC123DEFGHIJKLMN"
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
export AWS_SESSION_TOKEN="AQoDYXdzEJr......=="
# Method 2: Use AWS CLI profiles
aws configure set aws_access_key_id "ASIABC123DEFGHIJKLMN" --profile assumed-role
aws configure set aws_secret_access_key "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" --profile assumed-role
aws configure set aws_session_token "AQoDYXdzEJr......==" --profile assumed-role
# Test the assumed role permissions
aws sts get-caller-identity --profile assumed-role
{
"UserId": "AROABC123DEFGHIJKLMN:TestSession-1705317600",
"Account": "987654321098",
"Arn": "arn:aws:sts::987654321098:assumed-role/CrossAccountAccessRole/TestSession-1705317600"
}
Credential Usage Methods:
- Environment Variables: Set AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN
- CLI Profiles: Create a named profile with the temporary credentials
- SDK Configuration: Pass credentials programmatically in your application
- Instance Profile: For EC2 instances, use IAM roles for EC2
6. Cross-Account Assume Role Scenario
graph TB
subgraph "Account A (123456789012)"
DevTeam[Developer]
DevRole[Developer Role]
DevPolicies[Local Policies]
end
subgraph "Account B (987654321098)"
ProdRole[Production Role]
TrustPolicyB[Trust Policy]
ProdResources[Production Resources]
S3Bucket[S3 Bucket]
EC2Instance[EC2 Instance]
RDSDatabase[RDS Database]
end
subgraph "AWS STS"
STSService[Security Token Service]
TempCreds[Temporary Credentials]
end
DevTeam --> DevRole
DevRole -->|1. AssumeRole Request| STSService
STSService -->|2. Validate| TrustPolicyB
TrustPolicyB -->|3. Allow| STSService
STSService -->|4. Issue| TempCreds
TempCreds -->|5. Use Credentials| ProdResources
ProdResources --> S3Bucket
ProdResources --> EC2Instance
ProdResources --> RDSDatabase
style DevTeam fill:#e3f2fd
style ProdRole fill:#fff3e0
style STSService fill:#f3e5f5
style TempCreds fill:#e8f5e8
Cross-Account Scenario Explanation: This diagram shows a common cross-account access pattern where developers in Account A need to access production resources in Account B. The developer assumes a role in the production account, receives temporary credentials from STS, and uses those credentials to access production resources. This provides secure, auditable access without sharing long-term credentials.
Cross-Account Setup Commands
# In Account B (Production - 987654321098)
aws iam create-role \
--role-name ProductionAccessRole \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:role/DeveloperRole"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "prod-access-2024"
}
}
}
]
}'
# In Account A (Development - 123456789012)
aws iam put-role-policy \
--role-name DeveloperRole \
--policy-name AssumeProductionRole \
--policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::987654321098:role/ProductionAccessRole"
}
]
}'
Cross-Account Best Practices: Always use external IDs for cross-account access to prevent the confused deputy problem. Implement IP restrictions and MFA requirements where possible. Use CloudTrail to monitor cross-account role assumptions. Consider using AWS Organizations for centralized account management.
7. Common Issues and Troubleshooting
graph TD
Start[AssumeRole Request] --> TrustCheck{Trust Policy Valid?}
TrustCheck -->|No| TrustError[Access Denied - Trust Policy]
TrustCheck -->|Yes| PermCheck{Source Has Permission?}
PermCheck -->|No| PermError[Access Denied - No Permission]
PermCheck -->|Yes| CondCheck{Conditions Met?}
CondCheck -->|No| CondError[Access Denied - Conditions]
CondCheck -->|Yes| Success[Temporary Credentials Issued]
TrustError --> Debug1[Check Principal in Trust Policy]
PermError --> Debug2[Check Source Identity Permissions]
CondError --> Debug3[Check ExternalId, IP, MFA, etc.]
style TrustError fill:#ffcdd2
style PermError fill:#ffcdd2
style CondError fill:#ffcdd2
style Success fill:#c8e6c9
style Debug1 fill:#fff3e0
style Debug2 fill:#fff3e0
style Debug3 fill:#fff3e0
Troubleshooting Flow Explanation: This flowchart shows the decision tree for assume role operations and common failure points. Most issues fall into three categories: trust policy problems (role doesn't trust the source), permission problems (source can't assume roles), or condition problems (external ID, IP restrictions, MFA requirements not met).
Common Error Messages and Solutions
Error: "User: arn:aws:iam::123456789012:user/testuser is not authorized to perform: sts:AssumeRole"
Solution: The source identity doesn't have permission to assume the role. Add the sts:AssumeRole permission to the source identity's policies.
Error: "The request signature we calculated does not match the signature you provided"
Solution: Clock skew issue. Ensure system time is synchronized. Check AWS credentials are correct and not expired.
Error: "Access denied" when using temporary credentials
Solution: Check that the assumed role has the necessary permissions for the actions you're trying to perform. Verify the role's attached policies.
# Debugging commands
aws sts get-caller-identity
aws iam get-role --role-name CrossAccountAccessRole
aws iam list-attached-role-policies --role-name CrossAccountAccessRole
aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::123456789012:user/testuser \
--action-names sts:AssumeRole \
--resource-arns arn:aws:iam::987654321098:role/CrossAccountAccessRole
Additional Debugging Tips:
- Use AWS CloudTrail to track AssumeRole API calls and see detailed error information
- Check AWS Config for compliance and configuration drift
- Use IAM Policy Simulator to test permissions before deployment
- Verify all ARNs are correct and accounts exist
- Ensure regions are correctly specified in multi-region setups
Summary
AWS Assume Role is a critical security feature that enables secure, temporary access to AWS resources across accounts and services. The key components are:
- Trust Policy: Defines WHO can assume the role
- Permission Policy: Defines WHAT the role can do
- Temporary Credentials: Short-lived access tokens
- STS Service: Manages the credential issuance process
Always follow the principle of least privilege and use additional security measures like external IDs, IP restrictions, and MFA when appropriate.