The AccessDenied error when creating an IAM Role in Terraform means your AWS credentials lack the required iam:CreateRole permission. This can be caused by insufficient IAM permissions, permission boundaries, service control policies (SCPs), or missing trust policies. Resolve it by granting the necessary IAM permissions or adjusting your policy boundaries.
The AccessDenied error when creating an IAM Role indicates that your AWS credentials (the IAM user or role you're using to run Terraform) lack permission to create roles. AWS is rejecting your request to create a role because the identity you're authenticated as doesn't have the iam:CreateRole action in their identity-based policy. This is a permission issue, not a configuration issue—your Terraform code is fine, but your AWS credentials need more permissions. This commonly occurs when using IAM credentials with minimal permissions, when permission boundaries restrict your actions, when service control policies block the action at the organization level, or when your credentials are assumed from another role that lacks the necessary permissions.
First, check which AWS identity you're authenticated as and what permissions it has:
# Check your current identity
aws sts get-caller-identity
# Output shows the User/Role ARN you're using
# Example output:
# {
# "UserId": "AIDAJE45Q7YFFAREXAMPLE",
# "Account": "123456789012",
# "Arn": "arn:aws:iam::123456789012:user/terraform-user"
# }Note the ARN—this is the identity that needs the iam:CreateRole permission.
Check what permissions are attached to your credentials:
# If using an IAM user
aws iam list-user-policies --user-name terraform-user
aws iam list-attached-user-policies --user-name terraform-user
# If using a role
aws iam list-role-policies --role-name terraform-role
aws iam list-attached-role-policies --role-name terraform-role
# View a specific policy
aws iam get-user-policy --user-name terraform-user --policy-name policy-nameLook for "iam:CreateRole" in the policy Actions. If it's missing, that's the problem.
Add the necessary IAM permissions to your user or role. Your AWS administrator should attach a policy like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:CreateRole",
"iam:DeleteRole",
"iam:GetRole",
"iam:PassRole",
"iam:TagRole",
"iam:UntagRole",
"iam:UpdateRole",
"iam:AttachRolePolicy",
"iam:DetachRolePolicy",
"iam:PutRolePolicy",
"iam:DeleteRolePolicy",
"iam:ListRolePolicies",
"iam:ListAttachedRolePolicies"
],
"Resource": "*"
}
]
}For least privilege, restrict the Resource to your account's roles only:
"Resource": "arn:aws:iam::ACCOUNT_ID:role/*"Permission boundaries can restrict actions even if your identity-based policy allows them:
# Check if your user/role has a permission boundary
aws iam get-user --user-name terraform-user
aws iam get-role --role-name terraform-role
# Look for "PermissionsBoundary" in the output
# If present, check what it allows
aws iam get-policy --policy-arn arn:aws:iam::ACCOUNT:policy/boundary-policy
aws iam get-policy-version --policy-arn arn:aws:iam::ACCOUNT:policy/boundary-policy --version-id v1If a permission boundary exists and doesn't include iam:CreateRole, ask your AWS administrator to update it.
If you're in an AWS Organization, SCPs at the organization or account level can block IAM actions:
# This requires organizational permissions, but check with your organization admin
# SCPs are managed through AWS Organizations console or:
aws organizations list-policies --filter SERVICE_CONTROL_POLICY
# Check which SCPs are attached to your account
aws organizations list-accounts-for-parent --parent-id r-xxxIf SCPs block iam:CreateRole, contact your organization administrator to request an exemption or policy update.
If your Terraform credentials come from assuming a role in another account:
# Check the role you're assuming
aws iam get-role --role-name terraform-role
# Check its assume_role_policy (trust policy)
aws iam get-role-policy --role-name terraform-role --policy-name AssumeRolePolicyYour terraform AWS provider should have assume_role configured:
provider "aws" {
region = "us-east-1"
assume_role {
role_arn = "arn:aws:iam::ACCOUNT_ID:role/terraform-role"
}
}Ensure the terraform-role trust policy allows your source account/user to assume it.
Temporary credentials may expire or be invalid:
# Check credential expiration (if using temporary credentials)
aws sts get-session-token
# Try a simple AWS API call to verify credentials work
aws s3 ls
# If that fails, refresh your credentials:
# - For AWS CLI: aws configure or update ~/.aws/credentials
# - For environment variables: export AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
# - For temporary credentials: get new credentials from your identity providerIf credentials are stale or wrong, update them and retry terraform apply.
AWS sometimes provides encoded error details. If your error message includes an "Encoded authorization failure message", decode it:
aws sts decode-authorization-message \
--encoded-message '<really-long-encoded-string>' \
--query DecodedMessage \
--output textThis shows exactly what resource, action, and conditions were denied, helping pinpoint the exact permission or boundary causing the issue.
Least Privilege: Only grant iam:CreateRole if your Terraform configurations actually need to create roles. If Terraform only manages existing roles, use iam:UpdateRole, iam:AttachRolePolicy, and iam:PutRolePolicy instead.
Permission Boundaries: Permission boundaries are a best practice for limiting the maximum permissions a role can have. If you hit this issue, work with your security team to understand the boundary's intent and request an update if needed.
Service Control Policies: SCPs are a powerful but restrictive governance tool in AWS Organizations. If your organization blocks iam:CreateRole, escalate to your organization administrator or see if you need an exemption for infrastructure automation.
Session Tokens: If using temporary credentials (from STS, SSO, or AWS IAM Identity Center), ensure your session hasn't expired and has the right scope. Short-lived tokens may expire between terraform plan and terraform apply.
Cross-Account Access: For multi-account setups, always test that:
1. Your source account/user can assume the terraform role
2. The terraform role has the necessary permissions
3. Both identity-based and resource-based policies (trust relationship) are correct
Terraform AWS Provider Version: Very old versions of the AWS provider may have bugs around permission handling. Update if you're using provider version < 5.0:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}Error: Error installing helm release: cannot re-use a name that is still in use
How to fix "release name in use" error in Terraform with Helm
Error: Error creating GKE Cluster: BadRequest
BadRequest error creating GKE cluster in Terraform
Error: External program failed to produce valid JSON
External program failed to produce valid JSON
Error: Unsupported argument in child module call
How to fix "Unsupported argument in child module call" in Terraform
Error: network is unreachable
How to fix "network is unreachable" in Terraform