Skip to content
Latchkey

aws iam create-role: Trust Policies & Common CI Errors

Create an IAM role and the trust policy that says who may assume it.

aws iam create-role creates a role and its trust policy (assume-role policy). The trust policy is the half developers most often get wrong, especially for GitHub OIDC and cross-account access.

What it does

aws iam create-role --role-name <name> --assume-role-policy-document <doc> creates a role whose trust policy defines which principals (a service, account, or OIDC provider) may assume it. Permissions come separately from attached or inline policies; create-role only establishes identity and trust.

Common usage

Terminal
# Create a role trusted by an OIDC provider (e.g. GitHub Actions)
aws iam create-role \
  --role-name gha-deploy \
  --assume-role-policy-document file://trust.json

# Then attach permissions
aws iam attach-role-policy --role-name gha-deploy \
  --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess

Common error in CI: MalformedPolicyDocument / OIDC sub mismatch

create-role fails with "MalformedPolicyDocument: Has prohibited field Resource" (the trust policy uses Resource, which belongs in permission policies, not trust policies) or "Invalid principal in policy". And after creation, the deploy job gets "Not authorized to perform sts:AssumeRoleWithWebIdentity" because the trust policy’s Condition on token.actions.githubusercontent.com:sub does not match repo:OWNER/REPO:ref:refs/heads/main. Fix: a trust policy uses only Effect/Principal/Action/Condition (no Resource); set Action to sts:AssumeRoleWithWebIdentity and match the exact sub/aud conditions to your repo and branch.

Key options

OptionPurpose
--role-nameRequired role name
--assume-role-policy-documentTrust policy (file:// JSON)
--max-session-durationMax assumed-session length
attach-role-policyGrant permissions (separate call)

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →