Terraform Advanced — OPA & Conftest
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.