Terraform Advanced — OPA & Conftest

less than 1 minute read

Open-source policy enforcement for Terraform plans.


Workflow

# 1. Generate plan JSON
terraform plan -out=plan.tfplan
terraform show -json plan.tfplan > plan.json

# 2. Run policies
conftest test plan.json

Rego Policies

No Public S3 Buckets

# policy/s3.rego
package main

deny[msg] {
    resource := input.resource_changes[_]
    resource.type == "aws_s3_bucket"
    acl := resource.change.after.acl
    acl != "private"
    msg := sprintf("S3 bucket '%s' must be private, got '%s'",
                   [resource.name, acl])
}

Require Encryption

# policy/encryption.rego
package main

deny[msg] {
    resource := input.resource_changes[_]
    resource.type == "aws_ebs_volume"
    not resource.change.after.encrypted
    msg := sprintf("EBS volume '%s' must be encrypted",
                   [resource.name])
}

Cost Control

# policy/cost.rego
package main

expensive_types = {
    "aws_instance": {"m5.4xlarge", "m5.8xlarge", "p3.2xlarge"},
}

deny[msg] {
    resource := input.resource_changes[_]
    blocked := expensive_types[resource.type]
    resource.change.after.instance_type == blocked[_]
    msg := sprintf("Instance type %s is not allowed for cost control",
                   [resource.change.after.instance_type])
}

CI Integration

# In GitHub Actions
- name: Policy Check
  run: |
    terraform show -json plan.tfplan > plan.json
    conftest test plan.json --policy policy/

What’s Next?

Apply least-privilege IAM for Terraform.

← Sentinel Policies Least Privilege IAM →

Updated: