# Fix AWS IAM Role Trust Policy Error
You're trying to assume a role or configure cross-account access, but AWS keeps telling you the trust policy is invalid or you're not authorized. IAM trust policies are tricky because they work backwards from regular IAM policies—instead of saying "this identity can do X," they say "this identity is allowed to become this role."
The errors range from "Invalid principal in policy" to "User is not authorized to perform: sts:AssumeRole" and often leave you guessing where the actual problem lies.
Diagnosis Commands
First, understand which error you're getting. Try assuming the role:
aws sts assume-role \
--role-arn arn:aws:iam::123456789012:role/MyRole \
--role-session-name test-sessionIf this fails, the error message will hint at the issue. Let's examine the trust policy:
aws iam get-role \
--role-name MyRole \
--query 'Role.AssumeRolePolicyDocument' \
--output json | jq .Check if the role exists and get its basic info:
aws iam get-role \
--role-name MyRole \
--query 'Role.[RoleName,Arn,CreateDate,MaxSessionDuration]'Verify who you're currently authenticated as:
aws sts get-caller-identityCheck if your identity has permission to assume roles:
aws iam list-attached-user-policies \
--user-name $(aws sts get-caller-identity --query Arn --output text | cut -d'/' -f2)If you're using an instance profile or Lambda execution role, check the attached role policies:
aws iam list-role-policies --role-name MyRole
aws iam list-attached-role-policies --role-name MyRoleUse the policy simulator to test if you can assume the role:
aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::123456789012:user/my-user \
--action-names sts:AssumeRole \
--resource-arns arn:aws:iam::123456789012:role/MyRoleCommon Causes and Solutions
Invalid Principal in Trust Policy
Error: Invalid principal in policy
The trust policy references a principal that doesn't exist or is formatted incorrectly. A valid trust policy looks like:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:root"
},
"Action": "sts:AssumeRole",
"Condition": {}
}
]
}Common mistakes:
Wrong: Account ID without full ARN
``json
"Principal": { "AWS": "123456789012" }
Correct: Use full ARN or root
``json
"Principal": { "AWS": "arn:aws:iam::123456789012:root" }
Wrong: Missing account in service principal
``json
"Principal": { "Service": "ec2" }
Correct: Include full service name
``json
"Principal": { "Service": "ec2.amazonaws.com" }
Update the trust policy:
aws iam update-assume-role-policy \
--role-name MyRole \
--policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:root"
},
"Action": "sts:AssumeRole"
}
]
}'Cross-Account Access Denied
Error: User: arn:aws:iam::ACCOUNT-A:user/my-user is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::ACCOUNT-B:role/CrossAccountRole
For cross-account access, both sides need configuration:
In Account B (the role's account): The trust policy must allow Account A:
aws iam update-assume-role-policy \
--role-name CrossAccountRole \
--policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNT-A-ID:root"
},
"Action": "sts:AssumeRole",
"Condition": {}
}
]
}'In Account A (your account): Your identity needs permission to assume the role:
aws iam put-user-policy \
--user-name my-user \
--policy-name AssumeCrossAccountRole \
--policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::ACCOUNT-B-ID:role/CrossAccountRole"
}
]
}'To restrict to specific users in Account A, update the trust policy in Account B:
aws iam update-assume-role-policy \
--role-name CrossAccountRole \
--policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNT-A-ID:user/specific-user"
},
"Action": "sts:AssumeRole"
}
]
}'Service Role Trust Policy Error
Error: Invalid principal in policy when creating a service role
Service roles need the correct service principal. Here are common ones:
```json // EC2 "Principal": { "Service": "ec2.amazonaws.com" }
// Lambda "Principal": { "Service": "lambda.amazonaws.com" }
// ECS Tasks "Principal": { "Service": "ecs-tasks.amazonaws.com" }
// CloudFormation "Principal": { "Service": "cloudformation.amazonaws.com" }
// CodePipeline "Principal": { "Service": "codepipeline.amazonaws.com" }
// For services in specific regions (e.g., China) "Principal": { "Service": "ec2.amazonaws.com.cn" } ```
Create a service role:
aws iam create-role \
--role-name MyServiceRole \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}'Multiple Principals
When you need to allow multiple services or accounts:
aws iam update-assume-role-policy \
--role-name MultiPrincipalRole \
--policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::123456789012:root",
"arn:aws:iam::210987654321:root"
]
},
"Action": "sts:AssumeRole"
}
]
}'Or combine service and account principals:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:root"
},
"Action": "sts:AssumeRole"
}
]
}External ID Condition
For third-party access with External ID:
aws iam update-assume-role-policy \
--role-name ThirdPartyAccessRole \
--policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::THIRD-PARTY-ACCOUNT:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "my-unique-external-id-12345"
}
}
}
]
}'When assuming the role, include the External ID:
aws sts assume-role \
--role-arn arn:aws:iam::123456789012:role/ThirdPartyAccessRole \
--role-session-name third-party-session \
--external-id my-unique-external-id-12345MFA Condition Not Met
If the trust policy requires MFA:
{
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "true"
}
}
}You must use MFA when assuming the role:
```bash # Get MFA device ARN aws iam list-mfa-devices --user-name my-user
# Get session token with MFA aws sts get-session-token \ --serial-number arn:aws:iam::123456789012:mfa/my-user \ --token-code 123456
# Then assume role with the temporary credentials export AWS_ACCESS_KEY_ID=<from-session-token> export AWS_SECRET_ACCESS_KEY=<from-session-token> export AWS_SESSION_TOKEN=<from-session-token>
aws sts assume-role \ --role-arn arn:aws:iam::123456789012:role/MFARequiredRole \ --role-session-name mfa-session ```
Session Duration Issues
Error: The requested DurationSeconds exceeds the MaxSessionDuration set for this role
Check the role's max session duration:
aws iam get-role \
--role-name MyRole \
--query 'Role.MaxSessionDuration'If you need longer sessions, update the role:
aws iam update-role \
--role-name MyRole \
--max-session-duration 43200 # 12 hours in secondsThen specify the duration when assuming:
aws sts assume-role \
--role-arn arn:aws:iam::123456789012:role/MyRole \
--role-session-name long-session \
--duration-seconds 43200Session Name Condition
If the trust policy requires specific session name patterns:
{
"Condition": {
"StringLike": {
"sts:RoleSessionName": "admin-*"
}
}
}Use a matching session name:
aws sts assume-role \
--role-arn arn:aws:iam::123456789012:role/MyRole \
--role-session-name admin-john-sessionVerification Steps
After updating the trust policy, verify it works:
```bash # View the trust policy aws iam get-role \ --role-name MyRole \ --query 'Role.AssumeRolePolicyDocument' \ --output json | jq .
# Test assuming the role aws sts assume-role \ --role-arn arn:aws:iam::123456789012:role/MyRole \ --role-session-name test-session \ --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken,Expiration]'
# Use the assumed role aws sts get-caller-identity ```
For automated testing, create a script:
```bash #!/bin/bash ROLE_ARN="arn:aws:iam::123456789012:role/MyRole" SESSION_NAME="verify-session-$(date +%s)"
CREDENTIALS=$(aws sts assume-role \ --role-arn "$ROLE_ARN" \ --role-session-name "$SESSION_NAME" \ --output json)
if [ $? -eq 0 ]; then echo "Successfully assumed role: $ROLE_ARN" echo "Session expires: $(echo $CREDENTIALS | jq -r '.Credentials.Expiration')" else echo "Failed to assume role" exit 1 fi ```
Set up CloudTrail to monitor AssumeRole calls:
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=AssumeRole \
--start-time $(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ) \
--max-items 10 \
--query 'Events[*].[EventTime,Username,Resources[0].ResourceName]'