AWS IAM Trust Policies - Comprehensive Guide

Table of Contents

1. Overview of IAM Trust Policies

AWS IAM Trust Policies are JSON documents that define which principals (users, roles, or services) can assume a specific IAM role. They act as the gatekeeper for role assumption, establishing the trust relationship between the role and the entities that can use it.

graph TB A[Principal] -->|Requests| B[AssumeRole] B -->|Evaluates| C[Trust Policy] C -->|If Trusted| D[Temporary Credentials] C -->|If Not Trusted| E[Access Denied] D --> F[Role Permissions Applied] style A fill:#e1f5fe style C fill:#fff3e0 style D fill:#e8f5e8 style E fill:#ffebee style F fill:#f3e5f5
Trust Policy Flow Explanation:

This diagram shows the fundamental flow of trust policy evaluation. When a principal (user, role, or service) attempts to assume a role, AWS evaluates the trust policy attached to that role. If the principal is listed as trusted in the policy, temporary credentials are issued with the role's permissions. If not, access is denied immediately.

2. Key Concepts and Components

Trust Policy Structure

graph LR A[Trust Policy] --> B[Version] A --> C[Statement Array] C --> D[Effect] C --> E[Principal] C --> F[Action] C --> G[Condition] style A fill:#fff3e0 style B fill:#e8f5e8 style C fill:#e1f5fe style D fill:#f3e5f5 style E fill:#fff8e1 style F fill:#e8f4fd style G fill:#fce4ec
Trust Policy Components:

A trust policy consists of a version identifier and one or more statements. Each statement contains an Effect (Allow/Deny), Principal (who can assume), Action (what they can do), and optional Conditions (under what circumstances). The Principal element is what distinguishes trust policies from regular IAM policies.

Principal Types

graph TD A[Principal Types] --> B[AWS Account] A --> C[IAM User] A --> D[IAM Role] A --> E[AWS Service] A --> F[Federated User] A --> G[Anonymous User] B --> B1["arn:aws:iam::123456789012:root"] C --> C1["arn:aws:iam::123456789012:user/username"] D --> D1["arn:aws:iam::123456789012:role/rolename"] E --> E1["ec2.amazonaws.com"] F --> F1["arn:aws:iam::123456789012:saml-provider/provider"] G --> G1["*"] style A fill:#fff3e0 style B fill:#e8f5e8 style C fill:#e1f5fe style D fill:#f3e5f5 style E fill:#fff8e1 style F fill:#e8f4fd style G fill:#fce4ec
Principal Types Explained:

This diagram shows the different types of principals that can be specified in trust policies. AWS Account principals grant access to all users in an account, IAM Users are specific user ARNs, IAM Roles allow role chaining, AWS Services enable service-linked roles, Federated Users work with SAML/OIDC providers, and Anonymous Users (*) should be used with extreme caution.

3. Traffic Flow Diagrams

Cross-Account Role Assumption

sequenceDiagram participant U as User (Account A) participant STS as AWS STS participant R as Role (Account B) participant S as Service (Account B) U->>STS: aws sts assume-role STS->>R: Check Trust Policy R->>STS: Trust Policy Evaluation alt Trust Policy Allows STS->>U: Return Temporary Credentials U->>S: Access Service with Temp Creds S->>U: Service Response else Trust Policy Denies STS->>U: Access Denied end
Cross-Account Role Assumption Flow:

This sequence diagram illustrates how cross-account role assumption works. A user in Account A requests to assume a role in Account B through AWS STS. STS checks the role's trust policy, and if the user's account/principal is trusted, temporary credentials are issued. These credentials can then be used to access resources in Account B according to the role's permissions.

Service-Linked Role Flow

sequenceDiagram participant AWS as AWS Service participant STS as AWS STS participant Role as Service Role participant Resource as AWS Resource AWS->>STS: Assume Service Role STS->>Role: Verify Service Trust Policy Role->>STS: Service Listed in Principal STS->>AWS: Issue Service Credentials AWS->>Resource: Access Resource Resource->>AWS: Grant Access AWS->>Resource: Perform Operation
Service-Linked Role Flow:

This diagram shows how AWS services assume roles to perform operations on your behalf. Services like EC2, Lambda, or RDS assume roles with trust policies that explicitly trust the service. This is fundamental to AWS's security model, ensuring services only get the minimum permissions needed.

Federated Access Flow

sequenceDiagram participant User as External User participant IDP as Identity Provider participant STS as AWS STS participant Role as Federated Role participant AWS as AWS Services User->>IDP: Authenticate IDP->>User: Return SAML/OIDC Token User->>STS: AssumeRoleWithSAML/WebIdentity STS->>Role: Verify Trust Policy & Token Role->>STS: Trust Policy Allows IDP STS->>User: Return AWS Credentials User->>AWS: Access AWS Services
Federated Access Flow:

This sequence demonstrates federated access where external users authenticate with their identity provider (like Active Directory or Google) and then assume AWS roles. The trust policy must explicitly trust the identity provider, and the SAML/OIDC token is validated before credentials are issued.

Role Chaining Flow

graph TD A[Initial User] --> B[Assume Role 1] B --> C[Role 1 Trust Policy] C --> D[Temporary Creds 1] D --> E[Assume Role 2] E --> F[Role 2 Trust Policy] F --> G[Temporary Creds 2] G --> H[Access Final Resource] I[Trust Chain Validation] C --> I F --> I I --> J[Chain Length Check] J --> K[Max 1 Hour Session] style A fill:#e1f5fe style C fill:#fff3e0 style F fill:#fff3e0 style I fill:#ffebee style J fill:#ffebee style K fill:#ffebee
Role Chaining Flow:

This diagram illustrates role chaining, where one role assumes another role. Each role in the chain must have a trust policy that allows the previous role to assume it. AWS limits role chaining to prevent infinite loops and security issues. The maximum session duration decreases with each hop in the chain.

4. Setup Sequence and Commands

Command Execution Flow

graph TD A[Start Setup] --> B[1. Create Trust Policy Document] B --> C[2. Create IAM Role] C --> D[3. Attach Permission Policies] D --> E[4. Test Role Assumption] E --> F[5. Configure External Access] F --> G[6. Validate and Monitor] B --> B1[trust-policy.json] C --> C1[aws iam create-role] D --> D1[aws iam attach-role-policy] E --> E1[aws sts assume-role] F --> F1[Cross-account/Service config] G --> G1[CloudTrail monitoring] style A fill:#e8f5e8 style B fill:#e1f5fe style C fill:#fff3e0 style D fill:#f3e5f5 style E fill:#fff8e1 style F fill:#e8f4fd style G fill:#fce4ec
Setup Sequence Explanation:

This diagram shows the logical order for setting up IAM roles with trust policies. Each step builds upon the previous one, starting with creating the trust policy document, then the role itself, attaching permissions, testing functionality, configuring external access, and finally implementing monitoring. The sequence ensures a systematic approach to role creation.

Detailed Command Sequence

1 Create Trust Policy Document
cat > trust-policy.json << 'EOF' { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::123456789012:root" }, "Action": "sts:AssumeRole" } ] } EOF
2 Create IAM Role with Trust Policy
aws iam create-role \ --role-name CrossAccountAccessRole \ --assume-role-policy-document file://trust-policy.json \ --description "Role for cross-account access with trust policy"
3 Attach Permission Policies to Role
aws iam attach-role-policy \ --role-name CrossAccountAccessRole \ --policy-arn arn:aws:iam::aws:policy/ReadOnlyAccess
4 Test Role Assumption
aws sts assume-role \ --role-arn arn:aws:iam::987654321098:role/CrossAccountAccessRole \ --role-session-name TestSession \ --duration-seconds 3600
5 Verify Role Configuration
aws iam get-role --role-name CrossAccountAccessRole
6 List Attached Policies
aws iam list-attached-role-policies --role-name CrossAccountAccessRole

5. Detailed Configurations

Basic Trust Policy Configuration

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

Usage: This is the foundation trust policy that allows an entire AWS account to assume the role. Any user in account 123456789012 with appropriate permissions can assume this role.

Service Trust Policy Configuration

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
Service Trust Policy Parameters:

Usage: This trust policy enables EC2 instances to assume the role. Create this for EC2 instance profiles or when EC2 needs to access other AWS services on your behalf.

Multi-Principal Trust Policy

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": [ "arn:aws:iam::123456789012:user/AdminUser", "arn:aws:iam::123456789012:role/CrossAccountRole" ], "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
Multi-Principal Parameters:

Usage: This configuration allows specific users, roles, and services to assume the role. Use when you need granular control over who can assume the role rather than trusting an entire account.

Conditional Trust Policy

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::123456789012:root" }, "Action": "sts:AssumeRole", "Condition": { "StringEquals": { "sts:ExternalId": "UniqueExternalId123" }, "IpAddress": { "aws:SourceIp": "203.0.113.0/24" }, "DateGreaterThan": { "aws:CurrentTime": "2024-01-01T00:00:00Z" } } } ] }
Conditional Trust Policy Parameters:

Usage: Conditional trust policies add extra security layers. ExternalId is crucial for third-party access, IP restrictions limit geographic access, and time conditions enable temporary access windows.

Federated Trust Policy (SAML)

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::123456789012:saml-provider/CompanySAML" }, "Action": "sts:AssumeRoleWithSAML", "Condition": { "StringEquals": { "SAML:aud": "https://signin.aws.amazon.com/saml" } } } ] }
SAML Trust Policy Parameters:

Usage: This enables Single Sign-On (SSO) integration with corporate identity providers. Users authenticate with their corporate credentials and receive temporary AWS access based on their SAML attributes.

Web Identity Trust Policy (OIDC)

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "token.actions.githubusercontent.com:sub": "repo:myorg/myrepo:ref:refs/heads/main", "token.actions.githubusercontent.com:aud": "sts.amazonaws.com" } } } ] }
OIDC Trust Policy Parameters:

Usage: This example shows GitHub Actions integration where specific repositories can assume roles for CI/CD operations. The subject condition ensures only the specified repository and branch can assume the role.

Creating the Role with Trust Policy

aws iam create-role \ --role-name MyTrustedRole \ --assume-role-policy-document file://trust-policy.json \ --description "Role with comprehensive trust policy" \ --max-session-duration 43200 \ --tags Key=Purpose,Value=CrossAccountAccess Key=Environment,Value=Production
Create Role Parameters:

Sequence: This command must be run after creating the trust policy JSON file. It creates the role and establishes the trust relationship. The role exists but has no permissions until you attach policies.

Updating Trust Policy

aws iam update-assume-role-policy \ --role-name MyTrustedRole \ --policy-document file://updated-trust-policy.json
Update Trust Policy Parameters:

Sequence: Use this command to modify an existing role's trust policy. Changes take effect immediately. Be careful as this can break existing access if principals are removed.

Attaching Permission Policies

aws iam attach-role-policy \ --role-name MyTrustedRole \ --policy-arn arn:aws:iam::aws:policy/ReadOnlyAccess
aws iam put-role-policy \ --role-name MyTrustedRole \ --policy-name CustomInlinePolicy \ --policy-document file://custom-permissions.json
Permission Policy Parameters:

Sequence: Permission policies are attached after creating the role. They define what actions the role can perform, while trust policies define who can assume the role. You can attach multiple policies to a single role.

6. Advanced Scenarios

Cross-Account Access with External ID

sequenceDiagram participant C as Client (Account A) participant T as Third Party Service participant STS as AWS STS participant R as Role (Account B) C->>T: Request service with ExternalId T->>STS: AssumeRole with ExternalId STS->>R: Validate Trust Policy + ExternalId R->>STS: ExternalId matches STS->>T: Return temporary credentials T->>C: Perform service using credentials
External ID Flow:

This diagram shows how External IDs prevent confused deputy attacks in cross-account scenarios. When a third-party service needs access to your AWS account, you provide a unique External ID. The service must present this ID when assuming the role, ensuring only authorized parties can access your resources.

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::THIRD-PARTY-ACCOUNT:root" }, "Action": "sts:AssumeRole", "Condition": { "StringEquals": { "sts:ExternalId": "MyUniqueExternalId-2024-7f8e9d" } } } ] }
External ID Best Practices:

MFA-Required Trust Policy

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::123456789012:root" }, "Action": "sts:AssumeRole", "Condition": { "Bool": { "aws:MultiFactorAuthPresent": "true" }, "NumericLessThan": { "aws:MultiFactorAuthAge": "3600" } } } ] }
MFA Trust Policy Parameters:

Time-Limited Access Trust Policy

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::123456789012:user/TemporaryUser" }, "Action": "sts:AssumeRole", "Condition": { "DateGreaterThan": { "aws:CurrentTime": "2024-07-01T00:00:00Z" }, "DateLessThan": { "aws:CurrentTime": "2024-12-31T23:59:59Z" } } } ] }
Time-Limited Trust Policy:

Advanced Cross-Account Setup Commands

# Create trust policy for cross-account access with conditions cat > cross-account-trust.json << 'EOF' { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::123456789012:root" }, "Action": "sts:AssumeRole", "Condition": { "StringEquals": { "sts:ExternalId": "MyExternalId123" }, "Bool": { "aws:MultiFactorAuthPresent": "true" } } } ] } EOF
# Create the cross-account role aws iam create-role \ --role-name SecureCrossAccountRole \ --assume-role-policy-document file://cross-account-trust.json \ --description "Secure cross-account role with MFA and External ID"
# Create and attach custom permission policy cat > cross-account-permissions.json << 'EOF' { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:PutObject" ], "Resource": "arn:aws:s3:::my-shared-bucket/*" } ] } EOF
aws iam put-role-policy \ --role-name SecureCrossAccountRole \ --policy-name S3AccessPolicy \ --policy-document file://cross-account-permissions.json
# Test the role assumption from the trusted account aws sts assume-role \ --role-arn arn:aws:iam::TARGET-ACCOUNT:role/SecureCrossAccountRole \ --role-session-name CrossAccountSession \ --external-id MyExternalId123 \ --duration-seconds 3600

7. Troubleshooting

Common Trust Policy Issues

flowchart TD A[AssumeRole Failed] --> B{Check Trust Policy} B -->|Principal Missing| C[Add Principal to Trust Policy] B -->|Principal Incorrect| D[Verify Principal ARN] B -->|Condition Failed| E[Review Condition Logic] B -->|Action Missing| F[Add sts:AssumeRole] C --> G[Update Trust Policy] D --> G E --> G F --> G G --> H[Test Role Assumption] H -->|Success| I[Access Granted] H -->|Failure| J[Check Permissions Policy] style A fill:#ffebee style I fill:#e8f5e8 style J fill:#fff3e0
Troubleshooting Flow:

This flowchart shows the systematic approach to troubleshooting trust policy issues. Start by checking if the principal is correctly specified in the trust policy, then verify conditions are met, and finally ensure the correct action is allowed. If trust policy is correct but access still fails, check the permissions policies attached to the role.

Diagnostic Commands

# Check current user identity aws sts get-caller-identity
# View trust policy for a role aws iam get-role --role-name MyTrustedRole --query 'Role.AssumeRolePolicyDocument'
# List all policies attached to a role aws iam list-attached-role-policies --role-name MyTrustedRole
# Check inline policies aws iam list-role-policies --role-name MyTrustedRole
# Get specific inline policy aws iam get-role-policy --role-name MyTrustedRole --policy-name PolicyName
# Test role assumption with verbose output aws sts assume-role \ --role-arn arn:aws:iam::123456789012:role/MyTrustedRole \ --role-session-name TestSession \ --debug
Common Pitfalls:

Best Practices Summary

Practice Description Benefit
Least Privilege Only grant minimum required trust Reduces attack surface
External ID Use for third-party access Prevents confused deputy attacks
MFA Requirements Require MFA for sensitive roles Adds authentication layer
Time Restrictions Limit access to specific time windows Temporary access control
IP Restrictions Limit access to specific networks Geographic/network security
Regular Auditing Review trust policies periodically Maintains security posture

Conclusion

AWS IAM Trust Policies are the foundation of secure cross-account access, service integration, and federated identity management. By understanding the components, flows, and proper configuration techniques outlined in this guide, you can implement robust trust relationships that follow security best practices.

Remember that trust policies work in conjunction with permission policies - trust policies determine who can assume a role, while permission policies determine what that role can do. Both are essential for a complete security model.

Always test trust policies in a non-production environment before implementing them in production. Use CloudTrail to monitor role assumption activities and regularly audit your trust relationships for security compliance.