Every IAM user, group, and role in AWS has a unique, unambiguous identifier called an ARN (Amazon Resource Name) — formatted as arn:aws:iam::<account-id>:<resource-type>/<resource-name>. If you've ever been stuck debugging a trust policy, a cross-account access denial, or an AssumeRole failure, the root cause is almost always a malformed or mismatched ARN.
Key Takeaways
- The IAM ARN format is
arn:aws:iam::ACCOUNT_ID:user/UserNameorrole/RoleName— case-sensitive, account-specific. - A role ARN is what you reference in trust policies and
sts:AssumeRolecalls — not the role name alone. - IAM also assigns a separate, immutable unique ID (e.g.
AIDAJQABLZS4A3QDU576Q) and, for the root/IAM users, a canonical user ID used in S3 bucket policies. - Mixing up ARN vs. unique ID vs. canonical ID is the #1 cause of "principal not found" policy errors.
- ARNs are deleted and not reused — deleting and recreating a user with the same name produces a different unique ID internally, even though the ARN string looks identical.
Anatomy of an IAM ARN
arn:aws:iam::123456789012:user/jane.doe
arn:aws:iam::123456789012:group/Developers
arn:aws:iam::123456789012:role/LambdaExecutionRole
arn:aws:iam::123456789012:policy/CustomS3ReadOnly
Breaking down arn:aws:iam::123456789012:role/LambdaExecutionRole:
| Segment | Value | Meaning |
|---|---|---|
| Partition | aws | Standard AWS partition (vs. aws-cn, aws-us-gov) |
| Service | iam | The IAM service namespace |
| Region | (empty) | IAM is global — no region segment |
| Account ID | 123456789012 | The 12-digit account that owns this resource |
| Resource | role/LambdaExecutionRole | Resource type + name |
Finding Your ARNs via CLI
# Get the ARN of the currently authenticated IAM principal
aws sts get-caller-identity --query 'Arn' --output text
# -> arn:aws:iam::123456789012:user/jane.doe
# Get a specific role's full ARN and metadata
aws iam get-role --role-name LambdaExecutionRole \
--query 'Role.{Arn:Arn,RoleId:RoleId,CreateDate:CreateDate}'
{
"Arn": "arn:aws:iam::123456789012:role/LambdaExecutionRole",
"RoleId": "AROAJQABLZS4A3QDU576Q",
"CreateDate": "2024-03-11T09:22:41+00:00"
}
Note RoleId is NOT the ARN — it's the internal unique ID, useful for condition keys like aws:userid in policies but never used as the principal reference.
Role ARNs in Trust Policies
The most common place engineers get this wrong: trust policies require the full ARN of the trusted principal, not a bare account ID or role name.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:role/CrossAccountDeployRole"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "unique-partner-id-2024"
}
}
}
]
}
# Assume a role using its full ARN — not the role name alone
aws sts assume-role \
--role-arn arn:aws:iam::123456789012:role/CrossAccountDeployRole \
--role-session-name deploy-session \
--external-id unique-partner-id-2024
Canonical User ID vs. ARN vs. Unique ID
These three identifiers are not interchangeable, and conflating them is a frequent source of bugs:
<svg viewBox="0 0 740 300" xmlns="http://www.w3.org/2000/svg" style="width:100%;max-width:740px;font-family:sans-serif;color:currentColor">
<style>
.box { fill: none; stroke: currentColor; stroke-width: 1.5; }
.lbl { fill: currentColor; font-size: 13px; }
.sub { fill: currentColor; font-size: 11px; opacity: 0.75; }
.accent { fill: currentColor; opacity: 0.1; }
</style>
<rect x="20" y="30" width="220" height="90" class="box accent"/>
<text x="35" y="55" class="lbl">ARN</text>
<text x="35" y="75" class="sub">arn:aws:iam::123..:user/jane</text>
<text x="35" y="95" class="sub">used in policies, trust docs</text>
<rect x="270" y="30" width="220" height="90" class="box"/>
<text x="285" y="55" class="lbl">Unique ID</text>
<text x="285" y="75" class="sub">AIDAJQABLZS4A3QDU576Q</text>
<text x="285" y="95" class="sub">used in condition keys (aws:userid)</text>
<rect x="520" y="30" width="200" height="90" class="box accent"/>
<text x="535" y="55" class="lbl">Canonical ID</text>
<text x="535" y="75" class="sub">64-char hex string</text>
<text x="535" y="95" class="sub">used in S3 bucket ACLs/policies</text>
<text x="20" y="160" class="sub">All three identify the same IAM entity — but each is valid only in its own context.</text>
<text x="20" y="185" class="sub">Deleting + recreating a user with the same name changes the Unique ID, even if the ARN string matches.</text>
</svg>
# Get the canonical user ID (needed for S3 cross-account bucket policies)
aws s3api list-buckets --query 'Owner.ID' --output text
Common ARN Mistakes
- Using role name instead of full ARN in a trust policy
Principalfield — always fails silently withAccessDenied. - Hardcoding account IDs in ARNs across environments (dev/staging/prod) instead of templating them — breaks IaC portability.
- Assuming ARNs are reusable — if you delete
role/DeployRoleand recreate it, old policies referencing it by ARN string will match the name but the role's internal ID (and any conditions keyed on it) differs. - Confusing
aws:useridpolicy condition values — for IAM users it's the unique ID, for assumed roles it'srole-unique-id:session-name.
{
"Condition": {
"StringEquals": {
"aws:userid": "AROAJQABLZS4A3QDU576Q:deploy-session"
}
}
}
FAQ
What's the difference between an IAM role ARN and a role name? The role name (LambdaExecutionRole) is just the last segment. The ARN (arn:aws:iam::123456789012:role/LambdaExecutionRole) is the fully-qualified, globally unique identifier required in trust policies, resource policies, and cross-account references.
Why does my trust policy say the role doesn't exist when it clearly does? Usually the Principal field has the role name instead of the full ARN, or the account ID in the ARN is wrong. Verify with aws iam get-role --role-name <name> --query Role.Arn.
Is the canonical user ID the same as my AWS account ID? No. The canonical user ID is a separate 64-character identifier tied to the account's S3 resource ownership, used specifically in S3 ACLs and bucket policies — distinct from both the 12-digit account ID and the IAM ARN.
Can two IAM roles ever have the same ARN? No — ARNs are unique per account and resource type. However, if you delete a role and create a new one with the identical name, the ARN string will match the old one even though it's a logically different resource with a new unique ID.
Need Help Auditing IAM Policies and Trust Relationships?
Misconfigured ARNs in trust policies are one of the most common root causes of both access-denied incidents and accidental over-permissioning. F9 Infotech's AWS security team can audit your IAM roles, ARNs, and cross-account trust relationships for correctness and least-privilege compliance. Request an IAM security review from our cloud consultants.