TrademarkTrademark
Features
Documentation

Streamlining AWS IAM Role Creation with Terraform: A Practical Guide

Automate AWS IAM role creation with Terraform. This step-by-step guide covers modules, variables and least-privilege policies for fast, secure, reusable roles.
Sebastian StadilMarch 6, 2026Updated March 31, 2026
Streamlining AWS IAM Role Creation with Terraform: A Practical Guide
Key takeaways
  • Managing AWS IAM roles with Terraform brings automation, consistency, version control, reusability through modules, and easier adherence to least-privilege.
  • Core AWS provider resources for IAM roles include aws_iam_role, aws_iam_policy_document, aws_iam_policy, and aws_iam_role_policy_attachment.
  • Creating an EC2 IAM role involves defining a trust policy, defining permissions policies, attaching policies to the role, and creating an instance profile.
  • Best practices include least privilege, consistent naming, modular design, secure remote state with encryption, and regular audits of roles and policies.

AWS Identity and Access Management (IAM) decides who can do what in your account, so getting it right matters for security. Doing it by hand works until it doesn't. Once you have more than a handful of roles, clicking through the console leads to drift, copy-paste mistakes, and roles nobody remembers creating. Terraform lets you define those roles as code instead, so the configuration is the same every time you apply it.

This post walks through creating AWS IAM roles with Terraform: the resources you'll use, a worked EC2 example, and some practices worth following. Terraform handles the automation well on its own. What it doesn't solve is governance once you have many configurations and several teams touching them, and that's where a platform around Terraform starts to pay off.

Why Use Terraform for AWS IAM Roles?

Defining IAM roles in Terraform pays off in a few concrete ways once you get past the first role or two:

  • Automation and Consistency: When you define IAM roles and policies in code, you skip the manual setup and apply the same configuration across every environment. That cuts down on human error, and the code itself documents your security posture.
  • Version Control and Collaboration: Store IAM configurations in version control systems like Git. You get an audit trail, peer reviews for policy changes, easy rollbacks, and a place for the team to work together. Git covers the basics, and platforms built around Terraform add to it with centralized state management and role-based access control for Terraform operations.
  • Scalability and Reusability: Use Terraform modules to wrap up common IAM role patterns. This keeps you DRY (Don't Repeat Yourself), standardizes things, and makes updates simpler. A centralized module registry, often a feature in platforms like Scalr, makes it easier to find and reuse those components.
  • Adherence to Security Best Practices: When you codify IAM policies, the principle of least privilege (PoLP) gets easier to apply. Terraform's plan command lets you review what's about to change, so you catch misconfigurations before they go live.

Core Terraform Resources for AWS IAM Roles

Terraform's AWS provider offers specific resources for managing IAM roles and policies:

Resource/Data Source Name Primary Purpose Key Arguments/Attributes Example
aws_iam_role Defines an IAM role. name, assume_role_policy
aws_iam_policy_document (data) Generates a JSON IAM policy document. statement { actions, effect, resources, principals, condition }
aws_iam_policy Creates a customer-managed IAM policy. name, policy (JSON)
aws_iam_role_policy_attachment Attaches a managed policy (AWS or customer) to an IAM role. role, policy_arn
aws_iam_role_policy Creates an inline policy directly attached to an IAM role. role, policy (JSON)
aws_iam_role (inline_policy block) Exclusively manages inline policies for a role. inline_policy { name, policy }

These resources work together to define who can assume a role (trust policy) and what actions the assumed role can perform (permissions policies).

Step-by-Step: Creating an IAM Role with Terraform

Here's how to create an IAM role.

Step 1: Defining the Trust Policy (Assume Role Policy)

The trust policy specifies which principals (e.g., AWS services, users, other accounts) can assume the role. The aws_iam_policy_document data source is ideal for this.

data "aws_iam_policy_document" "ec2_assume_role_policy" {
  statement {
    effect  = "Allow"
    actions = ["sts:AssumeRole"] # Standard action for assuming a role
 
    principals {
      type        = "Service"
      identifiers = ["ec2.amazonaws.com"] # Allows EC2 service to assume this role
    }
  }
}
 
resource "aws_iam_role" "my_ec2_role" {
  name               = "MyApplicationEC2Role"
  assume_role_policy = data.aws_iam_policy_document.ec2_assume_role_policy.json
  description        = "IAM role for my application's EC2 instances"
  tags = {
    Environment = "production"
    ManagedBy   = "Terraform"
  }
}

This code defines a role that can be assumed by EC2 instances.

Step 2: Defining Permissions Policies

Permissions policies define what the role can do. You can use AWS managed policies or create custom ones. For custom policies, again, aws_iam_policy_document helps define the permissions, and aws_iam_policy creates the managed policy.

Example: Custom S3 Read-Only Policy

data "aws_iam_policy_document" "s3_read_only_permissions" {
  statement {
    effect    = "Allow"
    actions   = [
      "s3:GetObject",
      "s3:ListBucket"
    ]
    resources = [
      "arn:aws:s3:::my-application-bucket",
      "arn:aws:s3:::my-application-bucket/*"
    ]
  }
}
 
resource "aws_iam_policy" "s3_read_only_policy" {
  name        = "MyApplicationS3ReadOnly"
  description = "Grants read-only access to a specific S3 bucket"
  policy      = data.aws_iam_policy_document.s3_read_only_permissions.json
}

Step 3: Attaching Policies to the Role

Use aws_iam_role_policy_attachment to link your defined policies to the role.

resource "aws_iam_role_policy_attachment" "attach_s3_read_only" {
  role       = aws_iam_role.my_ec2_role.name
  policy_arn = aws_iam_policy.s3_read_only_policy.arn
}
 
# Attaching an AWS managed policy for SSM access
resource "aws_iam_role_policy_attachment" "attach_ssm_core" {
  role       = aws_iam_role.my_ec2_role.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}

Step 4: Creating an Instance Profile (for EC2 Roles)

For EC2 instances to use an IAM role, an instance profile is required.

resource "aws_iam_instance_profile" "my_ec2_profile" {
  name = "MyApplicationEC2Profile"
  role = aws_iam_role.my_ec2_role.name
}

This instance profile would then be associated with your EC2 instances at launch.

Best Practices for IAM Role Management with Terraform

  • Principle of Least Privilege (PoLP): Always grant only the minimum necessary permissions. Be specific with actions and resources.
  • Consistent Naming Conventions: Use clear, descriptive names for roles and policies to improve manageability.
  • Modular Design: Use Terraform modules for reusable IAM patterns. This works especially well when you manage them through a shared module registry.
  • Secure State Management: Keep Terraform state files safe with remote backends that use encryption and strict access controls. Platforms like Scalr can set up and manage secure state backends for you, so you don't have to wire up the plumbing yourself.
  • Regular Audits: Periodically review IAM roles and policies, removing unused or overly permissive ones.

Managing Complexity at Scale

Terraform automates the IAM work itself. Running it across a large organization, or dozens of AWS accounts, raises a different set of problems:

  • State File Management: Ensuring secure, consistent, and collaborative access to Terraform state files.
  • Policy Enforcement: Consistently applying organizational security policies and best practices across all Terraform configurations.
  • Collaboration & RBAC: Managing who can plan and apply changes to critical IAM infrastructure.
  • Visibility & Auditing: Maintaining a clear overview of all IAM resources defined by Terraform and their change history.

Platforms like Scalr handle these scaling problems. Scalr runs Terraform operations with hierarchical environment management, role-based access control (RBAC) for Terraform runs, integration with policy-as-code frameworks such as Open Policy Agent (OPA) for governance, and centralized auditing. Those features make it easier for teams to collaborate, stay compliant, and keep track of infrastructure like AWS IAM roles.

Where this leaves you

Managing AWS IAM roles with Terraform gives you a cloud setup that is more consistent and easier to audit. Once your roles and policies live in code, the same review and rollback workflow you already use for the rest of your infrastructure applies to them too.

The hard part shows up later, as more teams and accounts come into the picture. That's the point where a dedicated Terraform automation platform earns a look: it adds the access controls, policy enforcement, and audit history you need to run IAM at scale without losing track of who changed what.

About the author
Sebastian StadilCEO at Scalr
Sebastian Stadil is the CEO of Scalr with 15+ years of DevOps experience. He started with AWS in 2004 and advised early Microsoft Azure and Google Cloud.