Fix "Not Authorized to Perform iam:CreateRole" in AWS
If AWS just told you User: arn:aws:iam::123456789012:user/name is not authorized to perform: iam:CreateRole, the fix is almost always the same: your IAM identity is missing an explicit Allow for iam:CreateRole on the role's ARN, or something else in the chain — a permissions boundary, a service control policy, a resource control policy — is explicitly denying it. Here's the part that trips people up for hours: one denial anywhere in that chain beats every Allow you have, even if your user is sitting on AdministratorAccess. AWS evaluates every applicable policy and a single explicit deny wins outright, so "but I'm an admin" is not proof of anything until you've actually checked for a deny.
This error shows up in three very different situations that all print nearly identical text: a developer running aws iam create-role by hand, a CI/CD pipeline trying to stand up an execution role during a deploy, and a CloudFormation or CDK stack that needs to create a role on your behalf without you ever typing CreateRole yourself. Each one needs a slightly different fix, and mixing them up is the single biggest reason people re-attach the same broken policy three times and still see the error.
We're going to work through this in the order that actually saves you time: read the error correctly, rule out the boring cause first, then check the two causes almost nobody thinks to check — a permissions boundary and an organization-level policy — before you touch anything else.
What "not authorized to perform: iam:CreateRole" actually means
Break the error into its three parts and it stops being cryptic:
- User: the exact IAM identity that made the call — a user ARN like
arn:aws:iam::123456789012:user/name, or an assumed-role ARN likearn:aws:sts::123456789012:assumed-role/DeployRole/session-nameif a role, not a person, made the request. - is not authorized to perform: the exact API action AWS tried to run — here,
iam:CreateRole, the action behind the "Create role" button in the console and theaws iam create-roleCLI command. - on resource: the ARN of the role that would have been created. This tells you the intended role name even if the deploy failed before it existed.
This is a generic AWS pattern, not something specific to IAM — you'll see the identical shape ("User: [ARN] is not authorized to perform: [service]:[Action] on resource: [ARN]") for almost every AWS service, with the action name swapped in. Learning to read this one means you can read all of them.
It's worth separating this from a lookalike that confuses people constantly: iam:PassRole. CreateRole is about making a new role exist. PassRole is a completely different permission, needed when you hand an existing role to a service so that service can use it. If your error names PassRole instead of CreateRole, you don't need to create anything — you need permission to hand off a role you already have.
The five things that cause this error
AWS evaluates several layers of policy for every API call, and any one of them can be the culprit. This is why "I definitely have permission" and "I definitely got denied" can both be true at the same time.
| Cause | Where it lives | Who can see it |
|---|---|---|
No Allow statement for the action |
Identity-based policy on the user/role | You, in IAM → your user → Permissions |
Explicit Deny |
Identity-based, resource-based, or SCP | Account admin (SCPs need Organizations access) |
| Permissions boundary doesn't allow it | Boundary policy attached to your user/role | You, in IAM → Permissions boundary section |
| Service control policy (SCP) denies it org-wide | AWS Organizations | Organization management account only |
| You're calling the wrong action entirely | A service-linked role needs iam:CreateServiceLinkedRole, not iam:CreateRole |
You, by re-reading the exact action in the error |
🙋♂️ Jake's Reality Check
"I set up my nephew's laptop repair tracker on AWS last week and gave my own IAM user AdministratorAccess so I wouldn't have to deal with this stuff. It's still telling me I'm not authorized to create a role. How is that even possible?"
Because AdministratorAccess is only one policy among several that get checked, and it doesn't win automatically. If your account has a service control policy or a permissions boundary that denies iam:CreateRole, that deny applies on top of your admin policy, not instead of it. Admin access controls what you're allowed to do; it doesn't override a deny set by whoever manages the account or organization above you.
- Confirm the account and identity in the error. Copy the ARN from
User:in the error text and make sure it's the identity you think it is — a surprising number of "my policy is fine" reports turn out to be a different IAM user or an assumed role picking up unexpected credentials. - Open IAM → Users (or Roles) → that identity → Permissions policies. Look for a statement with
"Action": "iam:CreateRole"(or a wildcard like"iam:*") and"Effect": "Allow". If you don't see one anywhere in any attached policy, that's your answer — go to Fix 1. - Check the Permissions boundary section on the same page. If a boundary is set and it doesn't list
iam:CreateRoleas allowed, the boundary caps you below your identity policy no matter what the identity policy says — go to Fix 3. - If steps 2 and 3 both look fine, the deny is happening above your account. That's a service control policy, and only someone with access to the AWS Organizations management account can see it — go to Fix 2.
Fix 1: add the permission when it's simply missing
This is the most common cause by a wide margin: the identity simply was never granted iam:CreateRole. Full S3 access, EC2 access, or even a broad "PowerUser"-style policy doesn't include it — IAM permissions are entirely separate from every other service's permissions, on purpose, because IAM controls who can grant permissions in the first place.
- Sign in as (or ask) an account administrator, since granting IAM permissions itself requires IAM permissions.
- In the IAM console, go to Policies → Create policy → JSON, and add a statement granting
iam:CreateRole,iam:AttachRolePolicy,iam:PutRolePolicy, andiam:TagRole, scoped to a role name prefix. - Attach the policy to the user or role that needs it, under Permissions → Add permissions.
- Re-run the exact command or console action that failed. If it was a CLI call, no new credentials or re-login are needed — IAM permission changes take effect on the next API call, typically within seconds, occasionally up to a couple of minutes while the change propagates across AWS's edge caches.
⚠️ What this actually breaks if you go too wide
Granting iam:CreateRole with "Resource":"*" and no other guardrails lets that identity create a role with any name and any trust policy — including one that trusts their own account and can be assumed to grant themselves broader access than they started with. Scope the resource ARN to a name prefix your team controls, and see the least-privilege policy below before you copy-paste a wildcard into production.
Fix 2: find the explicit deny
An explicit deny is different from simply lacking a permission. A lacking permission is an implicit denial — nothing said yes, so the answer is no. An explicit deny is a policy that specifically says no to this action, and it beats every Allow anywhere else in the evaluation, full stop. This is the one situation where attaching more policies to yourself will never fix anything.
Explicit denies for iam:CreateRole usually come from one of three places:
- A deny statement in your own identity policy — rare, but check for it if someone on your team recently added a "guardrail" policy.
- A service control policy (SCP) set at the AWS Organizations level, often used to stop role creation outside an approved path — for example, a centralized IT team might allow
iam:CreateRoleonly under a specific/iam/path and explicitly deny it everywhere else, so a developer with full IAM permissions in their own account still gets denied the moment they try to create a role outside that path. - A permissions boundary with a matching deny — covered on its own below, since it behaves slightly differently.
It's worth knowing there's a second, newer organization-level policy type: resource control policies (RCPs), introduced alongside SCPs in late 2024. SCPs restrict what your principals — users and roles — are allowed to do. RCPs work the opposite direction, restricting who from outside your organization can reach into resources like S3 buckets, STS sessions, KMS keys, Secrets Manager secrets, and SQS queues. RCPs are unlikely to be the direct cause of a CreateRole denial for a principal acting from inside its own account, but if the identity in your error is assuming a role across an account boundary, an RCP covering STS is worth ruling out too.
"Ethan, if I've got full admin on this account, why would anyone even want to deny me anything?" Jake asked, staring at the same error for the third time that afternoon.
"Because your account isn't always the top of the chain," Ethan said. "The second your account joins an AWS Organization, someone above you — usually a platform or security team — can set rules that apply no matter what you grant yourself locally. It's not personal, and it's not a bug. It's the entire point of the feature."
If you have access to the AWS Organizations management account, check AWS Organizations → Policies → Service control policies for anything targeting your account or organizational unit with a Deny on iam:CreateRole. If you don't have that access, this is the point where you stop debugging and ask your account or platform administrator directly — there is no console view from inside your own account that shows you the SCP that's blocking you.
Fix 3: check for a permissions boundary
A permissions boundary is a policy attached directly to a user or role that sets a ceiling on what that identity's own permissions can ever grant — it doesn't hand out any permission by itself. If your identity policy allows iam:CreateRole but the boundary attached to you doesn't, the boundary wins: you can only do what both policies agree on.
This is easy to check but easy to miss because it's a separate section from your regular policies:
- Open IAM → Users (or Roles) and select the identity in question.
- Look for a Permissions boundary panel — if it says "Not set," this isn't your issue. If it names a policy, open it.
- Check whether that boundary policy's statements include
iam:CreateRoleunder an Allow. If it's absent from the boundary entirely, you're capped below it regardless of your identity policy. - Either ask the boundary's owner to add the action, or add it yourself if you're setting up automation, paired with the
iam:PermissionsBoundarycondition key so that anyone your automation creates is also forced to stay under a boundary — this is the standard pattern behind the CDK and CloudFormation error where role creation fails with "an explicit deny in a permissions boundary" even though nobody wrote that deny by hand.
The lookalike error: iam:CreateServiceLinkedRole
If your error actually reads iam:CreateServiceLinkedRole instead of iam:CreateRole, everything above still applies conceptually, but the fix is a different, narrower action. Service-linked roles are pre-defined roles that a specific AWS service creates and manages for itself — you don't design the trust policy or permissions, you only grant permission for the role to be created. AWS Config, RDS, EKS, and Auto Scaling are common services that need one the first time you use a related feature.
Grant it scoped to the exact service, never as a blanket allow:
{
"Effect": "Allow",
"Action": "iam:CreateServiceLinkedRole",
"Resource": "arn:aws:iam::*:role/aws-service-role/SERVICE-NAME.amazonaws.com/*",
"Condition": {
"StringLike": {"iam:AWSServiceName": "SERVICE-NAME.amazonaws.com"}
}
}
Replace SERVICE-NAME.amazonaws.com with the exact, case-sensitive service principal from that service's own documentation — never guess it, since the format varies and a wrong guess just produces the same denial with no useful clue why.
Why CloudFormation, CDK, and Terraform hit this even though you never called CreateRole
The identity in the error message isn't always a person — it's frequently an execution role that a deployment tool assumes to do its work. A CDK deploy assumes a bootstrap execution role; a CI/CD pipeline assumes a deploy role; Terraform assumes whatever role or user its provider is configured with. When any of these tools defines an IAM role inside your template or stack, that assumed role — not you — is the one making the CreateRole call, and it needs the permission and a clean boundary, not your personal user.
Two patterns account for almost every report of this in build logs:
- The pipeline's execution role is missing
iam:CreateRole. Fix it the same way as Fix 1, but attach the change to the pipeline's role, not your own user. - The pipeline's execution role has a permissions boundary applied to it, and any role it creates must also carry that same boundary. If your template creates a role without specifying a boundary, the call fails with an explicit deny even though your permissions look complete — the fix is to set the boundary on the new role explicitly wherever your infrastructure-as-code tool supports it, so the created role inherits the same ceiling as the identity creating it.
Tag conditions on role creation, and why they trip people up
A subtler cause worth knowing about even though it produces the same error text: your policy can allow iam:CreateRole but require specific tags on the new role, and forgetting to pass them fails the same way as having no permission at all. IAM supports request-level tag conditions on taggable actions, including role creation, using the aws:RequestTag and aws:TagKeys condition keys.
A policy enforcing this looks like the following — it allows creating a role, but only if the request includes a CostCenter tag with an approved value, and no other tag keys:
{
"Effect": "Allow",
"Action": "iam:CreateRole",
"Resource": "arn:aws:iam::123456789012:role/app-*",
"Condition": {
"StringEquals": {"aws:RequestTag/CostCenter": ["A-123","B-456"]},
"ForAllValues:StringEquals": {"aws:TagKeys": "CostCenter"}
}
}
If your team enforces something like this and your CreateRole call is missing the required tag entirely, or includes an extra tag key nobody approved, the request is denied with the exact same "not authorized to perform" message you started with — even though the base permission is present. When Fix 1 looks like it should have worked and the error hasn't budged, checking for a tag condition like this is worth doing before assuming the policy attachment failed.
Restricting who can create roles, and where
If you're on the side setting the policy rather than hitting the error, IAM paths let you split who can create roles by where those roles live, instead of an all-or-nothing grant. A centralized team can own everything under /iam/, while developer teams get a scoped path like /D1/ for their own service roles.
| Restriction type | Blocks by | Set by |
|---|---|---|
| Resource ARN scoping | Role name / name prefix | Account admin, identity policy |
| IAM path restriction | The /path/ segment of the role ARN | Account admin, identity policy or SCP |
| Permissions boundary requirement | Requiring iam:PermissionsBoundary on any new role | Account admin, identity policy |
| Org-wide deny | Account, OU, or entire organization | Organizations management account only |
A least-privilege policy that grants this safely
Rather than handing out iam:CreateRole on Resource: "*", scope it to a name prefix and require every role your team creates to carry a specific permissions boundary — this is the pattern platform and security teams use to let developers self-serve role creation without opening a path to privilege escalation.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["iam:CreateRole","iam:AttachRolePolicy","iam:PutRolePolicy"],
"Resource": "arn:aws:iam::123456789012:role/app-*",
"Condition": {
"StringEquals": {
"iam:PermissionsBoundary": "arn:aws:iam::123456789012:policy/DeveloperBoundary"
}
}
},
{
"Effect": "Deny",
"Action": ["iam:CreateRole","iam:PutRolePermissionsBoundary"],
"Resource": "*",
"Condition": {
"StringNotEquals": {
"iam:PermissionsBoundary": "arn:aws:iam::123456789012:policy/DeveloperBoundary"
}
}
}
]
}
✅ Why this is the one to use
"The first Allow does the job on its own for most teams — it's the Deny statement underneath that actually stops someone from quietly leaving the boundary off," Ethan said. "Without it, a developer can technically comply with the Allow by using the right name prefix, then skip the boundary entirely and hand their new role full account access. The Deny closes exactly that gap."
Testing the fix before you attach it
The IAM policy simulator lets you test whether a policy — attached or just pasted in as a draft — would allow a specific action against a specific resource ARN, without touching your live account. It has real limits worth knowing before you rely on it: it can only simulate one permissions boundary at a time, and it can't evaluate service control policies that have conditions attached, so a policy that passes the simulator can still fail in production if an SCP with conditions is involved.
To use it: open the IAM console, go to a user or role, choose the policy simulator link, select the action (iam:CreateRole), enter the resource ARN you intend to create, and run the simulation. It reports which specific statement allowed or denied the result, which is often faster than reading through several attached policies by eye.
When it's not IAM at all: the AWS Config "managed rule" version
If what you're actually chasing is a message about not being authorized to create a managed rule, that's a different action and a different service — AWS Config's InsufficientPermissionsException, thrown by PutConfigRule or PutOrganizationConfigRule. It looks similar in spirit but has a different root cause: it usually means the IAM role you assigned to AWS Config itself doesn't have permission to perform the underlying config:Put* action, or — for an organization-wide rule specifically — that the caller lacks permission to call IAM's GetRole action or to create the service-linked role AWS Config needs. If you landed here searching for a managed-rule permission error, check the role attached to your Config recorder rather than your own user policy; that's almost always where the fix lives.
🕐 What changed with organization-wide role creation
- Before: teams commonly attached broad IAM policies directly to developers to unblock CreateRole errors quickly.
- Now: permissions boundaries paired with a required-boundary condition are the standard way to grant self-service role creation without the privilege-escalation risk that a bare wildcard grant carries.
- What that means for you: if your organization recently tightened this, a policy that worked last quarter may now fail until a boundary is attached to the new role.
Frequently asked questions
What does "not authorized to perform" actually mean?
It means AWS evaluated all the policies that apply to the identity making the call and found no combination that allows the specific action on the specific resource — either because nothing granted it, or because something explicitly denied it.
Why does my user have other permissions but not iam:CreateRole?
IAM actions are managed separately from every other service's actions by design. A policy granting S3 or EC2 access says nothing about IAM unless it explicitly lists IAM actions too.
I have AdministratorAccess attached — why do I still get this error?
An explicit deny anywhere in the evaluation — an SCP, a resource-based policy, or a permissions boundary — overrides an Allow from AdministratorAccess. Admin access is one input to the decision, not an automatic override.
What's the difference between an implicit deny and an explicit deny?
An implicit deny happens when no policy allows the action — the default state for everything in AWS. An explicit deny happens when a policy specifically contains a Deny statement for that action, and it always wins over any Allow.
How do I find out which specific policy is blocking me?
Use the IAM policy simulator against the exact action and resource ARN — it names the statement that allowed or denied the result. For account-level policies, review your identity policies and permissions boundary directly in the IAM console.
Can my account admin always see why I was denied?
Only if the cause lives inside your account. A service control policy set at the AWS Organizations level is only visible to someone with access to the organization's management account, not to your account's own administrators.
Is it safe to just attach IAMFullAccess to fix this quickly?
It will unblock you, but it also grants full control over every user, role, and policy in the account, including the ability to grant yourself anything else. Scope the grant to iam:CreateRole on a specific resource ARN instead.
What's a least-privilege policy for iam:CreateRole?
Scope the resource to a name prefix your team owns and pair the Allow with a Deny that blocks role creation unless a specific permissions boundary is attached — this prevents someone from creating a role that has no meaningful permissions ceiling.
Why do I get a different error for iam:CreateServiceLinkedRole?
Service-linked roles are created and managed by AWS services themselves, so a separate, narrower action controls permission to let a service create one. Grant it scoped to the specific service principal, never as a blanket allow.
What is a permissions boundary, and how does it cause this error?
A permissions boundary is a policy attached to a user or role that caps what that identity's own policies can grant. If your identity policy allows CreateRole but your boundary doesn't, the boundary limits you to the more restrictive of the two.
Can a service control policy cause this even if my own account's policy allows it?
Yes. A service control policy applies on top of every identity policy in the affected accounts, and an explicit deny in an SCP blocks the action account-wide regardless of what any local policy allows.
Why does CloudFormation or CDK fail with this error even though I never called CreateRole myself?
The identity actually making the API call is the execution role your deployment tool assumes, not your personal user. That execution role needs the permission, and if it carries a permissions boundary, any role it creates typically needs the same boundary applied.
I'm getting "not authorized" when trying to enroll an MFA device — is that related?
It's the same family of error but a different action, typically iam:CreateVirtualMFADevice or iam:EnableMFADevice rather than CreateRole. The fix follows the same pattern: grant the specific action, usually scoped to the user's own ARN.
My CI/CD pipeline suddenly can't create roles anymore — what changed?
Nothing needs to have changed in your own template for this to start happening: an organization-wide policy tightened at the platform or security-team level, a new permissions boundary requirement, or an updated service control policy can all break a pipeline that was working the day before.
Can I restrict which paths or names a user can create roles under?
Yes. Scoping the resource ARN's path or name prefix in the identity policy, or enforcing it through a service control policy, lets a centralized team retain control over sensitive role paths while still letting developers create their own scoped roles.
How do I test a policy change before I attach it in production?
Use the IAM policy simulator to test the action against the target resource ARN before attaching the policy live. It only simulates one permissions boundary at a time and can't evaluate service control policies that include conditions.
- What is AWS IAM? A plain-English guide to cloud permissions
Start here if terms like "identity-based policy" or "permissions boundary" are still fuzzy — it covers the basics this post builds on.
Revision note. Written August 2026, covering current IAM policy evaluation behavior including permissions boundaries and organization-level service control and resource control policies. This will need a look whenever AWS changes how boundaries, SCPs, or RCPs interact with identity policies. If you've been stuck on this error for a while, you're not missing something obvious — the layered-policy design is genuinely confusing the first few times, and it gets faster to spot every time after.