AWS IAM Trust Policies - Complete Technical Guide
Overview: This guide provides comprehensive coverage of AWS IAM Trust Policies, including detailed Mermaid diagrams, traffic flow illustrations, configuration examples, and step-by-step AWS CLI commands with proper sequencing.
1. Introduction to IAM Trust Policies
IAM Trust Policies are JSON documents that define which entities (users, roles, services, or external accounts) can assume a particular IAM role. They are the cornerstone of AWS's security model for cross-account access, service delegation, and federated access patterns.
graph TD
A[Principal] -->|Requests| B[STS AssumeRole]
B -->|Validates| C[Trust Policy]
C -->|Allow| D[Temporary Credentials]
C -->|Deny| E[Access Denied]
D --> F[Role Permissions Applied]
F --> G[Access AWS Resources]
style A fill:#e1f5fe
style B fill:#fff3e0
style C fill:#f3e5f5
style D fill:#e8f5e8
style E fill:#ffebee
style F fill:#fff8e1
style G fill:#e0f2f1
Trust Policy Flow Explanation:
- Principal: The entity (user, role, service, or external account) requesting to assume the role
- STS AssumeRole: AWS Security Token Service validates the assume role request
- Trust Policy: The policy document that determines if the principal is allowed to assume the role
- Temporary Credentials: If allowed, STS issues temporary security credentials
- Role Permissions: The permissions attached to the role are applied to the temporary credentials
- Resource Access: The principal can now access AWS resources based on role permissions
2. Trust Policy Architecture Overview
graph LR
subgraph "Account A"
A1[IAM User]
A2[IAM Role]
A3[EC2 Instance]
end
subgraph "Account B"
B1[Target Role]
B2[Trust Policy]
B3[Permission Policies]
end
subgraph "AWS Services"
S1[Lambda]
S2[EC2]
S3[ECS]
end
subgraph "External Identity"
E1[SAML Provider]
E2[OIDC Provider]
E3[Web Identity]
end
A1 -->|AssumeRole| B1
A2 -->|AssumeRole| B1
A3 -->|AssumeRole| B1
S1 -->|AssumeRole| B1
S2 -->|AssumeRole| B1
S3 -->|AssumeRole| B1
E1 -->|AssumeRole| B1
E2 -->|AssumeRole| B1
E3 -->|AssumeRole| B1
B1 --> B2
B2 --> B3
style B1 fill:#ffcdd2
style B2 fill:#c8e6c9
style B3 fill:#bbdefb
Multi-Source Trust Policy Architecture:
This diagram illustrates how various principals from different sources can assume a role in Account B. The trust policy acts as the gatekeeper, determining which principals are allowed to assume the role. Once assumed, the role's permission policies determine what actions can be performed.
- Account A Principals: IAM users, roles, and EC2 instances from other AWS accounts
- AWS Services: Native AWS services that need to perform actions on your behalf
- External Identity: Federated users from external identity providers
- Target Role: The role being assumed with its trust and permission policies
3. Trust Policy Components Deep Dive
graph TB
subgraph "Trust Policy Document"
A[Version]
B[Statement Array]
subgraph "Statement Object"
C[Effect: Allow/Deny]
D[Principal]
E[Action]
F[Condition - Optional]
end
subgraph "Principal Types"
G[AWS Account]
H[IAM User]
I[IAM Role]
J[AWS Service]
K[Federated]
L[Anonymous]
end
end
B --> C
B --> D
B --> E
B --> F
D --> G
D --> H
D --> I
D --> J
D --> K
D --> L
style A fill:#e3f2fd
style B fill:#f3e5f5
style C fill:#e8f5e8
style D fill:#fff3e0
style E fill:#fce4ec
style F fill:#f1f8e9
Trust Policy Structure Breakdown:
This diagram shows the hierarchical structure of a trust policy document and the various principal types that can be specified.
- Version: Policy language version (typically "2012-10-17")
- Statement: Array of policy statements, each containing effect, principal, action, and optional conditions
- Effect: Allow or Deny - determines whether the statement allows or denies access
- Principal: Specifies who can assume the role (various types shown)
- Action: Usually "sts:AssumeRole" for trust policies
- Condition: Optional constraints like IP restrictions, MFA requirements, etc.
4. Basic Trust Policy Configuration
4.1 Simple Cross-Account Trust Policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:root"
},
"Action": "sts:AssumeRole"
}
]
}
Configuration Parameters:
- Version: "2012-10-17" - Current policy language version (required)
- Effect: "Allow" - Grants permission (alternative: "Deny")
- Principal.AWS: "arn:aws:iam::123456789012:root" - Allows entire AWS account 123456789012
- Action: "sts:AssumeRole" - The action being permitted
Alternative Principal Options:
- Specific User: "arn:aws:iam::123456789012:user/username"
- Specific Role: "arn:aws:iam::123456789012:role/rolename"
- Multiple Accounts: ["arn:aws:iam::123456789012:root", "arn:aws:iam::210987654321:root"]
Purpose: This basic trust policy allows any principal in the specified AWS account to assume the role. It's the foundation for cross-account access patterns.
4.2 AWS Service Trust Policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Configuration Parameters:
- Principal.Service: "lambda.amazonaws.com" - AWS Lambda service principal
Common Service Principals:
- EC2: "ec2.amazonaws.com"
- ECS: "ecs-tasks.amazonaws.com"
- API Gateway: "apigateway.amazonaws.com"
- CloudFormation: "cloudformation.amazonaws.com"
- CodeBuild: "codebuild.amazonaws.com"
Purpose: Service trust policies allow AWS services to assume roles on your behalf. This is essential for services like Lambda functions that need to access other AWS resources.
5. Advanced Trust Policy Patterns
5.1 Conditional Trust Policy with MFA
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:user/admin-user"
},
"Action": "sts:AssumeRole",
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "true"
},
"NumericLessThan": {
"aws:MultiFactorAuthAge": "3600"
}
}
}
]
}
Condition Parameters:
- Bool.aws:MultiFactorAuthPresent: "true" - Requires MFA to be present
- NumericLessThan.aws:MultiFactorAuthAge: "3600" - MFA must be within 1 hour (3600 seconds)
Other Condition Types:
- IpAddress: Restrict by source IP ranges
- StringEquals: Match exact string values
- DateGreaterThan/DateLessThan: Time-based conditions
- StringLike: Pattern matching with wildcards
Purpose: This pattern enforces additional security requirements beyond basic authentication. MFA requirements are crucial for high-privilege roles.
5.2 Federated Trust Policy (SAML)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456789012:saml-provider/ExampleProvider"
},
"Action": "sts:AssumeRoleWithSAML",
"Condition": {
"StringEquals": {
"SAML:aud": "https://signin.aws.amazon.com/saml",
"SAML:department": "Engineering"
}
}
}
]
}
Federated Configuration:
- Principal.Federated: ARN of the SAML identity provider
- Action: "sts:AssumeRoleWithSAML" - Specific action for SAML federation
- SAML:aud: SAML audience assertion
- SAML:department: Custom SAML attribute condition
SAML Assertion Attributes:
- SAML:sub: Subject identifier
- SAML:email: Email address
- SAML:name: Display name
- SAML:groups: Group membership
Purpose: Enables enterprise users to assume AWS roles using their corporate identity credentials through SAML federation.
6. Trust Policy Traffic Flow Diagrams
sequenceDiagram
participant U as User/Principal
participant STS as AWS STS
participant TP as Trust Policy
participant R as IAM Role
participant PP as Permission Policy
participant AWS as AWS Resources
U->>STS: 1. AssumeRole Request
STS->>TP: 2. Validate Principal
TP->>STS: 3. Allow/Deny Response
alt Trust Policy Allows
STS->>R: 4. Assume Role
R->>PP: 5. Get Permissions
PP->>STS: 6. Return Permissions
STS->>U: 7. Temporary Credentials
U->>AWS: 8. API Calls with Temp Creds
AWS->>PP: 9. Check Permissions
PP->>AWS: 10. Allow/Deny
AWS->>U: 11. Response
else Trust Policy Denies
STS->>U: 4. Access Denied
end
Trust Policy Traffic Flow Sequence:
This sequence diagram shows the complete flow of how trust policies work in the context of role assumption and resource access.
- AssumeRole Request: Principal requests to assume a role
- Validate Principal: STS checks the trust policy
- Allow/Deny Response: Trust policy returns decision
- Assume Role: If allowed, role is assumed
- Get Permissions: Role's permission policies are retrieved
- Return Permissions: Permissions are compiled
- Temporary Credentials: STS issues temporary credentials
- API Calls: Principal makes AWS API calls
- Check Permissions: AWS checks permission policies
- Allow/Deny: Permission decision is made
- Response: Result returned to principal
7. AWS CLI Commands and Setup Sequence
Command Execution Order
graph TD
A[1Create IAM Role] --> B[2Create Trust Policy]
B --> C[3Attach Trust Policy]
C --> D[4Create Permission Policy]
D --> E[5Attach Permission Policy]
E --> F[6Test AssumeRole]
F --> G[7Use Temporary Credentials]
style A fill:#e3f2fd
style B fill:#f3e5f5
style C fill:#e8f5e8
style D fill:#fff3e0
style E fill:#fce4ec
style F fill:#f1f8e9
style G fill:#e0f2f1
Setup Command Flow:
This diagram shows the proper sequence for setting up IAM roles with trust policies. Each step builds upon the previous one, creating a complete role assumption workflow.
7.1 Step 1: Create IAM Role with Trust Policy
aws iam create-role \
--role-name CrossAccountAccessRole \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "unique-external-id-12345"
}
}
}
]
}' \
--description "Role for cross-account access with external ID"
Command Parameters:
- --role-name: Name of the IAM role to create
- --assume-role-policy-document: Inline trust policy JSON
- --description: Human-readable description
Trust Policy Elements:
- Principal.AWS: The AWS account allowed to assume this role
- sts:ExternalId: Additional security measure for third-party access
Purpose: Creates the IAM role with an embedded trust policy. The external ID condition adds an extra layer of security for cross-account access scenarios.
7.2 Step 2: Create Trust Policy from File
# Create trust-policy.json file
cat > trust-policy.json << 'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::123456789012:user/admin-user",
"arn:aws:iam::123456789012:role/deployment-role"
]
},
"Action": "sts:AssumeRole",
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "true"
},
"IpAddress": {
"aws:SourceIp": ["203.0.113.0/24", "198.51.100.0/24"]
}
}
}
]
}
EOF
File-Based Trust Policy:
- Multiple Principals: Array of AWS ARNs allowed to assume the role
- MFA Condition: Requires multi-factor authentication
- IP Address Condition: Restricts access to specific IP ranges
Purpose: Creating trust policies as separate files makes them easier to manage, version control, and reuse across multiple roles.
aws iam create-role \
--role-name SecureAdminRole \
--assume-role-policy-document file://trust-policy.json \
--description "Secure admin role with MFA and IP restrictions"
File Reference:
- file://trust-policy.json: References the external JSON file
Best Practice: Using external files for policies allows for better version control, syntax validation, and easier collaboration among team members.
7.3 Step 3: Update Existing Trust Policy
aws iam update-assume-role-policy \
--role-name CrossAccountAccessRole \
--policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "updated-external-id-67890"
},
"DateGreaterThan": {
"aws:CurrentTime": "2024-01-01T00:00:00Z"
}
}
}
]
}'
Update Parameters:
- --role-name: Name of existing role to update
- --policy-document: New trust policy (completely replaces existing)
New Conditions:
- Updated External ID: Changed security token
- DateGreaterThan: Time-based access control
Purpose: Allows modification of existing trust policies without recreating the role. Useful for updating security requirements or adding new principals.
7.4 Step 4: Create and Attach Permission Policy
# Create permission policy
cat > permission-policy.json << 'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::example-bucket/*"
},
{
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::example-bucket"
}
]
}
EOF
Permission Policy Structure:
- Object Actions: GetObject, PutObject, DeleteObject for bucket contents
- Bucket Actions: ListBucket for the bucket itself
- Resource Separation: Different ARNs for bucket vs. objects
Purpose: Defines what actions the assumed role can perform. This is separate from the trust policy and controls resource access.
aws iam create-policy \
--policy-name S3AccessPolicy \
--policy-document file://permission-policy.json \
--description "S3 access policy for cross-account role"
Create Policy Parameters:
- --policy-name: Name for the managed policy
- --policy-document: JSON policy document
- --description: Policy description
Purpose: Creates a managed policy that can be attached to roles, users, or groups. Managed policies are reusable and versioned.
aws iam attach-role-policy \
--role-name CrossAccountAccessRole \
--policy-arn arn:aws:iam::YOUR-ACCOUNT-ID:policy/S3AccessPolicy
Attach Policy Parameters:
- --role-name: Role to attach the policy to
- --policy-arn: ARN of the managed policy
Purpose: Links the permission policy to the role. The role now has both a trust policy (who can assume it) and permission policies (what they can do).
7.5 Step 5: Test Role Assumption
aws sts assume-role \
--role-arn arn:aws:iam::TARGET-ACCOUNT-ID:role/CrossAccountAccessRole \
--role-session-name test-session-12345 \
--external-id unique-external-id-12345 \
--duration-seconds 3600
AssumeRole Parameters:
- --role-arn: ARN of the role to assume
- --role-session-name: Name for the session (appears in CloudTrail)
- --external-id: Must match the condition in trust policy
- --duration-seconds: Session duration (max 12 hours)
Purpose: Tests whether the trust policy allows the current principal to assume the role. Returns temporary credentials if successful.
7.6 Step 6: Use Temporary Credentials
# Extract credentials from assume-role response
export AWS_ACCESS_KEY_ID="ASIAEXAMPLE..."
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
export AWS_SESSION_TOKEN="AQoDYXdzEJr...[very long token]"
# Test access with temporary credentials
aws s3 ls s3://example-bucket/ --region us-west-2
Temporary Credential Usage:
- AWS_ACCESS_KEY_ID: Temporary access key
- AWS_SECRET_ACCESS_KEY: Temporary secret key
- AWS_SESSION_TOKEN: Session token (required for temporary credentials)
Purpose: Demonstrates using the temporary credentials to access AWS resources according to the role's permission policies.
8. Trust Policy Security Patterns
graph TD
subgraph "Security Layers"
A[Network Security]
B[Identity Verification]
C[Trust Policy Check]
D[Permission Policy Check]
E[Resource-Based Policy]
F[Service Control Policy]
end
subgraph "Trust Policy Controls"
G[Principal Validation]
H[Condition Evaluation]
I[MFA Requirements]
J[IP Restrictions]
K[Time-Based Access]
L[External ID]
end
A --> B
B --> C
C --> D
D --> E
E --> F
C --> G
G --> H
H --> I
H --> J
H --> K
H --> L
style C fill:#ffcdd2
style G fill:#c8e6c9
style H fill:#bbdefb
Security Layer Architecture:
This diagram shows how trust policies fit into AWS's defense-in-depth security model. Trust policies are evaluated early in the authorization process.
- Network Security: VPC, security groups, NACLs
- Identity Verification: Authentication of the principal
- Trust Policy Check: Can this principal assume the role?
- Permission Policy Check: What actions are allowed?
- Resource-Based Policy: Resource-specific permissions
- Service Control Policy: Organization-level guardrails
9. Common Trust Policy Patterns
9.1 Service-Linked Role Pattern
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"lambda.amazonaws.com",
"edgelambda.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
Service-Linked Pattern:
- Multiple Services: Lambda and Edge Lambda services
- No Conditions: Services don't typically require additional conditions
Use Case: Lambda functions that need to run in multiple regions or edge locations.
9.2 Cross-Account with Organization Unit
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"aws:PrincipalOrgID": "o-123456789"
},
"StringLike": {
"aws:PrincipalArn": "arn:aws:iam::*:role/OrganizationAccountAccessRole"
}
}
}
]
}
Organization-Based Trust:
- Principal: "*" allows any AWS principal
- aws:PrincipalOrgID: Restricts to your AWS Organization
- aws:PrincipalArn: Limits to specific role name pattern
Use Case: Allows any account in your organization to assume the role, but only through a specific role name.
10. Troubleshooting Trust Policies
graph TD
A[AssumeRole Call] --> B{Trust Policy Evaluation}
B -->|Allow| C[Success]
B -->|Deny| D[Access Denied]
D --> E[Check Principal ARN]
D --> F[Verify Conditions]
D --> G[Check Policy Syntax]
D --> H[Validate External ID]
D --> I[Check MFA Status]
D --> J[Verify IP Address]
E --> K[CloudTrail Logs]
F --> K
G --> K
H --> K
I --> K
J --> K
K --> L[Debug and Fix]
style D fill:#ffcdd2
style K fill:#fff3e0
style L fill:#c8e6c9
Trust Policy Troubleshooting Flow:
This diagram shows the systematic approach to troubleshooting trust policy issues.
- Trust Policy Evaluation: STS evaluates the policy against the request
- Common Issues: Incorrect ARNs, failed conditions, syntax errors
- CloudTrail Logs: Detailed logging for analysis
- Debug Process: Systematic checking of each component
10.1 Common Debugging Commands
# Get current caller identity
aws sts get-caller-identity
# Decode authorization message
aws sts decode-authorization-message \
--encoded-message "encoded-message-from-error"
# Check role trust policy
aws iam get-role \
--role-name CrossAccountAccessRole \
--query 'Role.AssumeRolePolicyDocument'
# Simulate policy evaluation
aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::123456789012:user/test-user \
--action-names sts:AssumeRole \
--resource-arns arn:aws:iam::123456789012:role/CrossAccountAccessRole
Debugging Commands:
- get-caller-identity: Shows current AWS identity
- decode-authorization-message: Decodes error details
- get-role: Retrieves role configuration including trust policy
- simulate-principal-policy: Tests policy evaluation
Purpose: These commands help identify and resolve common trust policy issues.
Important Security Notes:
- Always use external IDs for third-party access
- Implement MFA requirements for high-privilege roles
- Use IP restrictions when possible
- Regularly audit and rotate trust policies
- Monitor CloudTrail for unexpected AssumeRole calls
11. Best Practices Summary
Trust Policy Best Practices:
- Principle of Least Privilege: Grant only necessary permissions
- Use Conditions: Add IP, MFA, and time-based restrictions
- External IDs: Always use for third-party access
- Regular Audits: Review and update policies regularly
- CloudTrail Monitoring: Track all AssumeRole activities
- Policy Versioning: Use managed policies for version control
- Testing: Validate policies before production deployment
Conclusion: AWS IAM Trust Policies are fundamental to secure cross-account access, service delegation, and federated identity management. Understanding their structure, implementation, and security patterns is crucial for maintaining robust AWS security posture.