The awsiampolicy resource represents the Terraform abstraction for an AWS IAM policy object. The resource creates a policy that defines explicit allow and deny privileges to specific resources or resource groups. The associated IAM policy determines the privileges available to an IAM identity. Policies are JSON documents that define explicit allow and deny privileges to specific resources or resource groups. The configuration examined in the reference material builds an IAM user, an S3 bucket, maps permissions for that bucket with an IAM policy, and finally attaches that policy to the new user. The workflow can be completed using Terraform Community Edition or HCP Terraform. HCP Terraform is a platform that can be used to manage and execute Terraform projects. It includes features like remote state and execution, structured plan output, workspace resource summaries, and more. The tutorial assumes familiarity with Terraform and HCP Terraform workflows. If new to Terraform, the Get Started collection is the prerequisite path.
The policy document used in the example contains two statements. 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. This separation of listing scope versus object scope is a practical illustration of least privilege in practice. Listing buckets requires a broad resource target because the ListAllMyBuckets action is account scoped. Operating on a specific bucket requires a precise ARN target.
Policy Resource Definition and Terraform Integration
The awsiampolicy resource is created with a name attribute constructed from a random pet identifier and a description attribute. The resource block in the reference configuration shows:
hcl
resource "aws_iam_policy" "policy" {
name = "${random_pet.pet_name.id}-policy"
description = "My test policy"
policy = data.aws_iam_policy_document.example.json
}
The policy attribute is set to the JSON output of the awsiampolicy_document data source. Prior to the change, the policy attribute was set via a heredoc string:
hcl
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 heredoc approach is acceptable for simple policies or one-off configurations. As policies grow more complex and begin to be reused throughout the environment, it can be difficult to parse policies using heredoc strings. The migration from heredoc to a data source reflects a maturation of configuration hygiene.
The iampolicy resource and iampolicy_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. The separation between policy creation and policy attachment is a critical security boundary in AWS. Creating a policy without attaching it produces an orphaned permission object that has no effect on any identity.
Policy attachment is performed with a dedicated resource:
hcl
resource "aws_iam_user_policy_attachment" "attachment" {
user = aws_iam_user.new_user.name
policy_arn = aws_iam_policy.policy.arn
}
The policy attachment resource has two required attributes: the user and the policyarn. The user attribute references the IAM user name created in this configuration. The policyarn attribute references the ARN of the policy created by awsiampolicy. Without this attachment step, the policy remains inert in AWS.
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. Resource interpolation allows the bucket ARN to be constructed from the awss3bucket resource, ensuring the policy always targets the correct resource even if the bucket name changes.
Policy Document Generation with awsiampolicy_document
The awsiampolicydocument 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 awsiam_policy resource.
The data source makes applying policies to AWS resources more flexible. You can overwrite, append, or update policies with this resource by using the sourcepolicydocuments and overridepolicydocuments arguments. The data source makes it easier to reuse policies throughout your environment. Terraform error checking automatically formats your policy document into correct JSON when you run your apply.
The example data source configuration is:
hcl
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 statement uses resources = ["arn:aws:s3:::"] to match the ListAllMyBuckets action. The second statement uses resources = [aws_s3_bucket.bucket.arn] to restrict s3: to the specific bucket created in the configuration.
The move from heredoc JSON to HCL statement blocks reduces parsing errors. JSON requires strict comma placement and quoting. HCL provides native syntax for arrays and interpolation. The error checking performed by Terraform during apply catches malformed statements before they reach AWS.
Identity-Based Versus Resource-Based Policy Models
A policy is an object in AWS that, when associated with an identity or resource, defines their permissions. When you create a permissions policy to restrict access to a resource, you can choose an identity-based policy or a resource-based policy.
Identity-based policies are attached to an IAM user, group, or role. These policies let you specify what that identity can do. For example, you can attach the policy to the IAM user named John, stating that he is allowed to perform the Amazon EC2 RunInstances action. The policy could further state that John is allowed to get items from an Amazon DynamoDB table named MyCompany. You can also allow John to manage his own IAM security credentials. Identity-based policies can be managed or inline.
Resource-based policies are attached to a resource. For example, you can attach resource-based policies to Amazon S3 buckets, Amazon SQS queues, VPC endpoints, AWS Key Management Service encryption keys, Amazon DynamoDB tables and streams, and AWS Sign-In resources. With resource-based policies, you can specify who has access to the resource and what actions they can perform.
AWS policies, as the name implies, allow you to set permissions to access your AWS resources. This is essential for controlling who can do what with your AWS services. There are two types of policies:
- Resource based policy
- Identity based policy
The awsiampolicy resource creates an identity-based policy. It is a managed policy that can be attached to users, groups, or roles. The S3 bucket policy would be a resource-based policy attached directly to the bucket.
Statement Elements and Resource Targeting
An AWS IAM policy is a JSON document that defines permissions in AWS. Each policy contains one or more statements — small blocks that specify whether an action is allowed or denied against a resource under optional conditions. Policies attach to identities or users, groups, roles or to resources such as S3 buckets, KMS keys, SNS topics and are the language the IAM evaluation engine speaks when it authorizes every single AWS API call.
Because policies can be combined, inherited, and bounded via SCPs, permission boundaries, and session policies, IAM policies are the single most important security surface in an AWS account — and also the single most common source of access-related misconfigurations.
Every IAM policy statement has up to six fields:
| Field | Description |
|---|---|
| Version | Usually "2012-10-17" the current policy language version; required for condition keys |
| Effect | Allow or Deny |
| Action | The API operations the statement applies to, e.g., s3:GetObject, dynamodb:Query. Wildcards are supported |
| Resource | One or more Amazon Resource Names |
| Principal | Required in resource-based policies to identify who the statement applies to |
The Resource element in an IAM policy statement defines the object or objects that the statement applies to. Statements must include either a Resource or a NotResource element. You specify a resource using an Amazon Resource Name. The format of the ARN depends on the AWS service and the specific resource you're referring to. Although the ARN format varies you always use an ARN to identify a resource.
Note: Some AWS services do not allow you to specify actions for individual resources. In these cases, any actions that you list in the Action or NotAction element apply to all resources in that service.
In the example policy, the first statement uses Resource "". The Action s3:ListAllMyBuckets requires Resource "". The second statement uses Resource "${awss3bucket.bucket.arn}" to restrict s3:* to a single bucket.
For full access to S3, an example policy would include:
- Version: The version number of the policy language
- Statement: The key part of the policy
- Effect: Can be either Allow or Deny
- Action: Specifies the actions that are allowed. The s3:* wildcard means all actions on Amazon S3 are allowed, including creating, listing, and deleting buckets, uploading and downloading objects, setting permissions, etc.
- Resource: Specifies the resources that the actions apply to. The * wildcard means all resources. In the context of S3, it means all buckets and all objects within those buckets.
Policy Attachment Requirement and User Binding
You must assign explicit permissions to IAM identities to enable their access AWS resources. The associated IAM policy determines the privileges available to an IAM identity. Without a policy attachment, the policy exists but does not grant any access.
The attachment resource connects the policy ARN to a specific user. The user attribute uses awsiamuser.newuser.name. The policyarn attribute uses awsiampolicy.policy.arn. This binding is the moment when the permission graph becomes active.
In practice, this means that after terraform apply completes the awsiampolicy resource, the policy is created in AWS but no identity can use it. Only after the awsiamuserpolicyattachment resource is created does the IAM user gain the ability to list buckets and operate on the specific bucket.
Managed Versus Inline Policy Distinctions
Managed Policies:
- Managed policies can be either AWS-managed or user-managed
- AWS-managed policies are created and maintained by AWS
The awsiampolicy resource creates a user-managed managed policy. It is stored as a separate policy object and can be attached to multiple identities. Inline policies are embedded directly in a user, group, or role and cannot be shared.
Managed policies provide reuse. The same policy can be attached to many users. Inline policies provide tighter coupling but reduce reusability.
Error Checking and Reusability Advantages
Terraform data sources make it easier to reuse policies throughout your environment. Reuse reduces drift and ensures consistent least privilege across accounts.
Terraform error checking automatically formats your policy document into correct JSON when you run your apply. This prevents syntax errors that would cause AWS API rejections.
The sourcepolicydocuments and overridepolicydocuments arguments allow policy composition. You can build base policies and then extend them for specific roles without duplicating JSON.
The impact of these advantages is significant for teams operating multiple AWS accounts. A single source of truth for IAM policies reduces misconfigurations. The principle of least privilege is easier to audit when policies are defined in HCL rather than freeform JSON.
Conclusion
The awsiampolicy resource in Terraform provides a declarative mechanism to create IAM policies that define explicit allow and deny privileges to specific resources. The resource works in concert with the awsiampolicydocument data source to convert HCL statements into valid JSON policy documents. The first example statement allows listing every S3 bucket in the account via Resource "*". The second statement allows any S3 action on a specific bucket via resource interpolation. Policy creation does not equate to policy enforcement. A separate awsiamuserpolicyattachment resource must bind the policy ARN to a user name to activate permissions. Identity-based policies attach to users, groups, or roles and define what an identity can do. Resource-based policies attach to services such as S3 buckets, SQS queues, KMS keys, and DynamoDB tables and define who can access the resource. Every statement can contain Version, Effect, Action, Resource, and Principal elements. Resource targeting uses ARNs, and some services require Resource "*". Managed policies can be AWS-managed or user-managed. Writing policies with the awsiampolicydocument data source improves flexibility, reusability, and error checking compared to heredoc JSON. The combination of these constructs enables repeatable, auditable, least-privilege IAM policy management in AWS through Terraform.