liveBook · Manning

Policy

As explained in Terraform in Depth: Infrastructure as Code with Terraform and OpenTofu

A policy is a rule set that governs technical, compliance, financial, or contractual decisions about infrastructure and software.

A policy turns a decision into a rule. In infrastructure work, that might mean allowing an EC2 instance to access another AWS service or preventing a costly configuration choice before deployment. section 4.1.4 section 7.5

For AWS permissions, IAM policies combine resources with allowed actions. A role receives those policies and can be assigned to a machine. An EC2 module can provide an IAM role and instance profile, then expose the role so each project can add its own permissions rather than forcing the module to anticipate every service. section 4.1.4

Listing 4.4 Creating a role
data "aws_iam_policy_document" "instance_assume_role_policy" { #1
  statement {                                                  #2
    actions = ["sts:AssumeRole"]
 
    principals {
      type        = "Service"
      identifiers = ["ec2.amazonaws.com"]                      #3
    }
  }
}
 
resource "aws_iam_role" "main" {
  name               = "${var.name_prefix}-instance-role"      #4
  assume_role_policy = data.aws_iam_policy_document.instance_assume_role_
policy.json                                                  #5
}
 
resource "aws_iam_instance_profile" "main" {                   #6
  name = aws_iam_role.main.name                                #7
  role = aws_iam_role.main.name
}
 
 
resource "aws_instance" "hello_world" {
  count                = var.instance_count
  ami                  = data.aws_ami.ubuntu.id
  subnet_id            = var.subnet_id
  instance_type        = var.instance_type
  iam_instance_profile = aws_iam_instance_profile.main.name    #8
 
  tags = merge(var.tags, {
    Name = "${var.name_prefix}-${count.index}"
  })
}
#1 This data source helps us build custom IAM policies. We could use a template or JSON string, but that is more error prone.
#2 AWS Services need permission to use the roles we create.
#3 We are giving the EC2 service permission to use this role, but no other services can.
#4 We’re using the name prefix to ensure that the role has a unique name. Creating two modules with the same name will cause an error.
#5 This is the json generated by our data source.
#6 AWS Instances need a “profile” attached to the “role” to use them with AWS Instances.
#7 It’s best practice to name the profile the same as the role that it works with.
#8 Update our aws_instance definition with our new profile.

The role setup uses an assume-role policy document for EC2 and connects the role to an instance profile. section 4.1.4

A policy can also enforce a team decision in infrastructure code. For example, choosing AWS GP2 storage instead of the faster, cheaper GP3 option is not a code error, but a rule can still catch it. OPA policies use Rego; TFLint’s OPA plugin can raise an issue when a Terraform resource violates one. section 7.5 section 7.5.1

Listing 7.30 OPA example policy
package tflint
 
import rego.v1
 
deny_invalid_s3_bucket_name contains issue if {               #1
    buckets := terraform.resources("aws_s3_bucket", {"bucket": "string"}, 
{})                                                         #2
    name := buckets[_].config.bucket
    not startswith(name.value, "example-com-")                #3
 
    issue := tflint.issue(`Bucket names should always start with 
"example-com-"`, name.range)                                #4
}
#1 This is where the policy name comes from.
#2 This call looks through resources for S3 buckets.
#3 If the name starts with “example-com-” then the policy ends here and the issue isn’t created.
#4 This last step saves the generated issue so it gets raised by TFLint.

This Rego rule finds S3 buckets whose names lack a required prefix and emits a TFLint issue at the bucket-name attribute. section 7.5.1

Choose the enforcement path deliberately: TFLint’s OPA plugin is experimental and is most useful when a team already uses OPA; Checkov offers an easier route to custom policies. Review every scanner finding. Fix unintended violations, and document the reason for any intentional exception so reviewers can assess it later. section 7.5.1 section 7.4.1

How Terraform in Depth: Infrastructure as Code with Terraform and OpenTofu covers it

How deep it goes
Explains IAM role wiring and walks through a Rego naming rule, while directing readers to plugin documentation for fuller policy construction.
Examples
Uses GP3 versus GP2 storage and a required S3 bucket-name prefix to illustrate enforceable decisions.
What it assumes
Introduces IAM and role-based access control from basics; recommends OPA with TFLint chiefly for teams already using OPA.
What you can do after
Apply it via TFLint’s OPA plugin to flag a naming violation, or diagnose Checkov findings and document intentional exceptions.
How it connects
Connects policies to IAM roles, instance profiles, Terraform resources, OPA, Rego, and TFLint.

Also explained in

Compare how 13 books explain policy →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Terraform in Depth: Infrastructure as Code with Terraform and OpenTofu. The section links point to the parts of the book it draws on.