AWS Assume Role - Complete Guide

Table of Contents

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

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:

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:

Always follow the principle of least privilege and use additional security measures like external IDs, IP restrictions, and MFA when appropriate.