Create IAM Policies | Terraform | HashiCorp Developer (2022)

You must assign explicit permissions to IAM identities (users, groups, or roles) to enable their access AWS resources. The associated IAM policy determines the privileges available to an IAM identity. Policies are JSON documents that define explicit allow/deny privileges to specific resources or resource groups.

There are advantages to managing IAM policies in Terraform rather than manually in AWS. With Terraform, you can reuse your policy templates and ensure the principle of least privilege with resource interpolation.

In this tutorial, you will create an IAM user and an S3 bucket. Then, you will map permissions for that bucket with an IAM policy. Finally, you will attach that policy to the new user and learn how to iterate on more complex policies.

You can complete this tutorial using the same workflow with either TerraformOSS or Terraform Cloud. Terraform Cloud is a platform that you can use tomanage and execute your Terraform projects. It includes features like remotestate and execution, structured plan output, workspace resource summaries, andmore.

Select the Terraform OSS tab to complete this tutorial using Terraform OSS.

This tutorial assumes that you are familiar with the Terraform and TerraformCloud workflows. If you are new to Terraform, complete the Get Started collection first. If you are new to Terraform Cloud, complete the Terraform Cloud Get Startedtutorials first.

For this tutorial, you will need:

  • Terraform v1.2+ installed locally.
  • A Terraform Cloud account and organization.
  • Terraform Cloud locally authenticated.
  • The AWS CLI.
  • An AWS account with IAM administrative permissions.
  • A Terraform Cloud variable set configured with your AWS credentials.

This tutorial assumes that you are familiar with the Terraform workflow. If you are new to Terraform, complete the Get Started collection first.

For this tutorial, you will need:

Clone the example repository

Clone the Create IAM policies with Terraform repository.

$ git clone

Change into the repository directory.

$ cd learn-terraform-iam-policy

The IAM policy resource is the starting point for creating an IAM policy in Terraform.

The file contains an IAM policy resource, an S3 bucket, and a new IAM user. Open the file in your code editor and review the IAM policy resource. The name in your policy is a random_pet string to avoid duplicate policy names.

resource "aws_iam_policy" "policy" { name = "${}-policy" description = "My test policy" policy = <<EOT{ "Version": "2012-10-17", "Statement": [ { "Action": [ "s3:ListAllMyBuckets" ], "Effect": "Allow", "Resource": "*" }, { "Action": [ "s3:*" ], "Effect": "Allow", "Resource": "${aws_s3_bucket.bucket.arn}" } ]}EOT}

The resource's policy attribute uses a multi-line heredoc string. For simple policies or one-off configurations, this approach is acceptable. However, as your policies grow more complex and you begin to reuse them throughout your environment, it can be difficult to parse policies using heredoc strings.

Refactor your policy

The aws_iam_policy_document data source uses HCL to generate a JSON representation of an IAM policy document. Writing the policy as a Terraform configuration has several advantages over defining your policy inline in the aws_iam_policy resource.

  • Terraform data sources makes applying policies to your AWS resources more flexible. You can overwrite, append, or update policies with this resource by using the source_policy_documents and override_policy_documents arguments.
  • Terraform data sources make it easier to reuse policies throughout your environment.
  • Terraform error checking automatically formats your policy document into correct JSON when you run your apply.

Copy the aws_iam_policy_document configuration below into your file. This data source uses HCL syntax to define the same IAM privileges as the policy in the heredoc string.

data "aws_iam_policy_document" "example" { statement { actions = ["s3:ListAllMyBuckets"] resources = ["arn:aws:s3:::*"] effect = "Allow" } statement { actions = ["s3:*"] resources = [aws_s3_bucket.bucket.arn] effect = "Allow" }}

Both statements in this policy apply to any user, group, or role with this policy attached. The first policy statement allows the user to list every S3 bucket in the AWS account. The second policy statement allows the user to perform any action on the bucket you create in this configuration, but not on other buckets in the account.

Update your iam_policy resource policy attribute to use the IAM policy document and save your changes.

 resource "aws_iam_policy" "policy" {  name = "${}-policy"  description = "My test policy"+ policy = data.aws_iam_policy_document.example.json- policy = <<EOT- {- "Version": "2012-10-17",- "Statement": [- {- "Action": [- "s3:ListAllMyBuckets"- ],- "Effect": "Allow",- "Resource": "*"- },- {- "Action": [- "s3:*"- ],- "Effect": "Allow",- "Resource": "${aws_s3_bucket.bucket.arn}"- }- ]- }- EOT }

The iam_policy resource and iam_policy_document data source used together will create a policy, but this configuration does not apply this policy to any users or roles. You must create a policy attachment for your policy to apply to your users.

In your file, add a new policy attachment resource to apply your policy to the user created in this configuration.

resource "aws_iam_user_policy_attachment" "attachment" { user = policy_arn = aws_iam_policy.policy.arn}

The policy attachment resource has two required attributes: the user and the policy_arn. Terraform interpolates your policy Amazon Resource Name (ARN) from your previously defined iam_policy resource when you apply this configuration. Each AWS resource has an ARN, and Terraform passes that unique identifier to the AWS API.

This resource assigns your policy to a specific user. If you are creating a group or a role, you can use the group or role attachment resources instead.

Add an output for your JSON-rendered policy to the end of your file.

output "rendered_policy" { value = data.aws_iam_policy_document.example.json}

Create your user, bucket, and policy

Now that you have created and attached a policy in your configuration, apply your changes.

Set the TF_CLOUD_ORGANIZATION environment variable to your Terraform Cloudorganization name. This will configure your Terraform Cloud integration.


In your terminal, initialize your Terraform configuration. Terraform will automatically create the learn-terraform-aws-iam-policy workspace in your Terraform Cloud organization.

$ terraform initInitializing Terraform Cloud...Initializing provider plugins...- Reusing previous version of hashicorp/aws from the dependency lock file- Installing hashicorp/aws v4.4.0...- Installed hashicorp/aws v4.4.0 (signed by HashiCorp)Terraform Cloud has been successfully initialized!You may now begin working with Terraform Cloud. Try running "terraform plan" tosee any changes that are required for your infrastructure.If you ever set or change modules or Terraform Settings, run "terraform init"again to reinitialize your working directory.

Note: This tutorial assumes that you are using a tutorial-specificTerraform Cloud organization with a global variable set of your AWScredentials. Review the Create a Credential VariableSet for detailed guidance. If you are using a scoped variable set, assign it to your new workspace now.

Open your file and comment out the cloud block that configures the Terraform Cloud integration.

terraform { /* cloud { workspaces { name = "learn-terraform-aws-iam-policy" } } */ required_providers { aws = { source = "hashicorp/aws" version = "~> 4.4.0" } } required_version = ">= 1.2"}

Initialize this configuration.

$ terraform initInitializing the backend...##...Terraform has been successfully initialized!You may now begin working with Terraform. Try running "terraform plan" to seeany changes that are required for your infrastructure. All Terraform commandsshould now work.If you ever set or change modules or backend configuration for Terraform,rerun this command to reinitialize your working directory. If you forget, othercommands will detect it and remind you to do so if necessary.

Apply your configuration. Enter yes when prompted to accept your changes.

$ terraform apply## ...Apply complete! Resources: 5 added, 0 changed, 0 destroyed.Outputs:rendered_policy = <<EOT{ "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Action": "s3:ListAllMyBuckets", "Resource": "arn:aws:s3:::*" }, { "Sid": "", "Effect": "Allow", "Action": "s3:*", "Resource": "arn:aws:s3:::primarily-liberal-spider-bucket" } ]}EOT

The output should contain a rendered policy with the complete ARN of your newly created bucket.

Test this policy in the AWS Policy Simulator. This tool lets you test an IAM policy by simulating whether a user would be allowed to run AWS operations.

Use the Policy Simulator to test if your user can delete any objects or buckets in the S3 service.

  1. First, select new_user, then your policy name from the left sidebar. Your policy name should start with your random animal and -policy-.
  2. In the "Select service" drop-down, select "S3".
  3. In the "Select actions" drop-down, choose "DeleteObject" and "DeleteBucket".
  4. Click "Run Simulation" and verify the simulator denies both actions as intended.

Create IAM Policies | Terraform | HashiCorp Developer (1)

Next, test if your user can delete objects in the test bucket you created or delete the bucket itself.

  1. Copy the ARN of your test bucket. Your ARN should start with arn:aws:s3:::<RANDOM_ANIMAL>-bucket-.
  2. Expand the simulation result drop-down for each action and add the bucket ARN, replacing the existing * character.
  3. Select "Run Simulation" and verify the simulator allows both actions as intended.

Create IAM Policies | Terraform | HashiCorp Developer (2)

Clean up your infrastructure

Before moving on, destroy the infrastructure you created in this tutorial.

$ terraform destroy

Respond to the confirmation prompt with yes.

If you used Terraform Cloud for this tutorial, after destroying your resources, delete the learn-terraform-aws-iam-policy workspace from your Terraform Cloud organization.

In this tutorial, you created and refactored an AWS IAM policy with Terraform. To learn more about creating policies with Terraform, consider the resources below.

  • S3 bucket policies differ from IAM policies. To learn more about S3 bucket policy resources, review the S3 bucket policy resource.
  • The templatefile() function allows you to create templatized policies for use in your configuration.
  • For an alternate to heredoc formatting, use the jsonencode() function.
  • Learn how to create default tags for AWS resources.
  • Learn how to use AssumeRole to Provision AWS Resources.

Top Articles

Latest Posts

Article information

Author: Rueben Jacobs

Last Updated: 12/27/2022

Views: 6080

Rating: 4.7 / 5 (57 voted)

Reviews: 80% of readers found this page helpful

Author information

Name: Rueben Jacobs

Birthday: 1999-03-14

Address: 951 Caterina Walk, Schambergerside, CA 67667-0896

Phone: +6881806848632

Job: Internal Education Planner

Hobby: Candle making, Cabaret, Poi, Gambling, Rock climbing, Wood carving, Computer programming

Introduction: My name is Rueben Jacobs, I am a cooperative, beautiful, kind, comfortable, glamorous, open, magnificent person who loves writing and wants to share my knowledge and understanding with you.