AWS IAM Policies with Terraform: Complete Guide
AWS IAM Policies with Terraform is one of the most practical skills you can learn when managing AWS infrastructure as code.
Instead of creating permissions manually in the AWS Management Console, Terraform allows you to define, version, review, and deploy IAM policies alongside the rest of your infrastructure. This approach reduces configuration drift and makes security changes easier to audit.
If you're new to AWS identity management, start by learning how to create users, groups, and roles with Terraform in our guide on AWS IAM with Terraform.
Why Use AWS IAM Policies with Terraform?
AWS Identity and Access Management (IAM) policies define what actions are allowed or denied on AWS resources.
When an IAM user is created, it has no permissions by default. Access is granted through policies attached directly to users, groups, or roles.
Managing these permissions with Terraform provides several advantages:
- Version control for every permission change
- Repeatable deployments across environments
- Easier code reviews and audits
- Reduced risk of manual configuration errors
- Consistent security policies across teams
Imagine onboarding multiple developers across development, staging, and production environments. Creating permissions manually may work initially, but it quickly becomes difficult to maintain. Terraform keeps permissions consistent everywhere.
Before creating IAM policies, ensure your Terraform AWS provider is configured correctly. If you haven't done that yet, see our guide on Using Terraform Providers.
How to Create AWS IAM Policies with Terraform
Terraform provides the aws_iam_policy resource for creating customer-managed IAM policies.
The policy itself must be supplied in JSON format, following AWS IAM policy syntax.
Official references:
Define an IAM Policy Inline
For learning purposes and small examples, you can define the policy directly inside your Terraform configuration using heredoc syntax.
resource "aws_iam_policy" "admin_policy" {
name = "AdminAccessPolicy"
description = "Administrative access policy"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}
EOF
}
This creates a customer-managed IAM policy in AWS.
Production Tip: Use Policy Documents Instead of Raw JSON
Inline JSON works for demonstrations, but most production environments use the Terraform aws_iam_policy_document data source.
Benefits include:
- Built-in validation
- Easier maintenance
- Better readability
- Reduced JSON formatting errors
Example:
data "aws_iam_policy_document" "s3_read_only" {
statement {
effect = "Allow"
actions = [
"s3:GetObject"
]
resources = [
"arn:aws:s3:::example-bucket/*"
]
}
}
resource "aws_iam_policy" "s3_read_only" {
name = "S3ReadOnlyPolicy"
policy = data.aws_iam_policy_document.s3_read_only.json
}
For larger Terraform projects, this approach is usually easier to manage than embedding raw JSON.
How to Attach an IAM Policy to an AWS User
Creating a policy does not automatically grant permissions.
To assign permissions, you must attach the policy to an IAM user, group, or role.
Terraform provides the aws_iam_user_policy_attachment resource for this purpose.
resource "aws_iam_user_policy_attachment" "attach_admin" {
user = aws_iam_user.lucy.name
policy_arn = aws_iam_policy.admin_policy.arn
}
Terraform automatically understands the dependency between the IAM policy and the attachment through resource references.
If you're unfamiliar with Terraform dependencies, check out our guide on Resource Dependencies in Terraform.
Attaching Multiple Policies
A user can have multiple policies attached.
Example:
resource "aws_iam_user_policy_attachment" "s3_access" {
user = aws_iam_user.lucy.name
policy_arn = aws_iam_policy.s3_access.arn
}
resource "aws_iam_user_policy_attachment" "cloudwatch_access" {
user = aws_iam_user.lucy.name
policy_arn = aws_iam_policy.cloudwatch_access.arn
}
For larger organizations, attaching policies to groups or roles is usually preferred over attaching policies directly to users.
Managing IAM Policies with External JSON Files
As policies grow, storing JSON in separate files becomes easier to manage.
This keeps infrastructure code clean while allowing security teams to review policies independently.
Step 1: Create a JSON Policy File
Create a file named admin-policy.json.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}
Step 2: Load the File in Terraform
Terraform's built-in file() function can load the contents of the JSON file.
resource "aws_iam_policy" "admin_policy" {
name = "AdminAccessPolicy"
policy = file("admin-policy.json")
}
This approach keeps Terraform configurations shorter and easier to maintain.
Common Mistake to Avoid
Terraform will successfully create policies even when permissions are overly broad.
For example:
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
While useful for testing, this grants full administrative access.
In production environments, follow the principle of least privilege and grant only the permissions required for a specific workload.
Deploy the IAM Policy Using Terraform
Once the configuration is complete, deploy it using standard Terraform commands.
terraform init
terraform plan
terraform apply
Each command serves a different purpose:
terraform initdownloads providers and initializes the working directory.terraform planpreviews infrastructure changes.terraform applycreates or updates resources.
For a deeper explanation of Terraform commands, see our guide on Terraform Commands Explained.
Security Best Practices for AWS IAM Policies with Terraform
IAM policies directly control access to AWS resources, so security should always be part of the implementation process.
Follow these recommendations:
- Never hardcode AWS credentials in Terraform code.
- Use IAM roles whenever possible.
- Apply the principle of least privilege.
- Store Terraform state securely.
- Review permissions regularly.
- Enable logging and monitoring for IAM activities.
- Use version control for policy changes.
A common mistake is granting AdministratorAccess during testing and forgetting to remove it later. Restrict permissions from the beginning to avoid accidental privilege escalation.
If you're managing Terraform state remotely, consider using:
- Remote Backends in AWS S3 with Terraform
- Remote State and State Locking in Terraform
These practices improve collaboration and reduce operational risk.
Real-World IAM Architecture Example
In modern AWS environments, policies are often attached to IAM roles instead of individual users.
A common setup looks like this:
- Developers authenticate through AWS Identity Center.
- Users assume temporary roles.
- IAM policies are attached to those roles.
- Access is granted only for the duration of the session.
This approach reduces long-term credential management and aligns with AWS security best practices.
When Should You Use Terraform Modules for IAM?
As the number of policies grows, managing everything in a single Terraform file becomes difficult.
Terraform modules help organize IAM resources into reusable building blocks.
Consider modules when:
- Multiple teams need similar permissions
- The same policy is reused across environments
- IAM configurations exceed a few resources
- You want consistent permission patterns
Learn more in our guides on:
- Creating and Using Modules in Terraform
- Using Modules from Registry in Terraform
- Terraform Registry
Frequently Asked Questions (FAQs)
What is an IAM policy in AWS?
An IAM policy is a JSON document that defines what actions are allowed or denied on AWS resources.
Can I define IAM policies in separate files when using Terraform?
Yes. Terraform provides the file() function, which allows policies to be stored in external JSON files and loaded into Terraform configurations.
What is the best way to create IAM policies in Terraform?
For production environments, the aws_iam_policy_document data source is generally preferred because it improves readability and validation.
How do I attach multiple IAM policies to a user?
You can create multiple aws_iam_user_policy_attachment resources or attach policies through IAM groups and roles.
Should I use IAM users or IAM roles?
AWS generally recommends IAM roles and temporary credentials instead of long-lived IAM user credentials whenever possible.
Key Takeaways
- AWS IAM policies control access to AWS resources.
- Terraform can create and manage IAM policies through code.
- Policies can be defined inline, loaded from JSON files, or generated using
aws_iam_policy_document. - IAM roles are typically preferred over direct user-based permissions.
- Following least-privilege principles improves security and reduces risk.
- Terraform modules help manage IAM resources at scale.
8 free, 100% client-side tools for developers — no signup, no data uploads.
Explore all tools