Write a security policy in OPA/Rego, attach it to an IaC project, and watch it block a non-compliant Terraform deployment before anything reaches your cloud.
Your team is deploying S3 buckets but some are being created without server-side encryption. You want to:
can_policies IAM permission (admin role has this by default)Policy groups organize related policies and get attached to projects as a unit.
S3 Security Policies| Field | Value |
|---|---|
| Name | Require S3 Encryption |
| Description | All S3 buckets must have server-side encryption enabled |
| Category | Security |
| Severity | Critical |
Policy content (OPA/Rego):
package main
deny[msg] {
input.resource.type == "aws_s3_bucket"
not has_encryption(input.resource)
msg := sprintf(
"S3 bucket '%v' must have server-side encryption enabled. Add an aws_s3_bucket_server_side_encryption_configuration block.",
[input.resource.name]
)
}
has_encryption(resource) {
resource.values.server_side_encryption_configuration[_].rule[_].apply_server_side_encryption_by_default[_]
}
Click Save Policy.
The policy group is now active on that project. Every future deployment will be checked against it.
To see the policy in action, try deploying an S3 bucket without encryption:
# This will be BLOCKED by the policy
resource "aws_s3_bucket" "insecure" {
bucket = "my-insecure-bucket"
}
Run a Plan on this code. When you try to apply, the policy engine evaluates the plan JSON and returns:
Policy Check: FAILED
✗ CRITICAL Require S3 Encryption
Resource: aws_s3_bucket.insecure
Message: S3 bucket 'insecure' must have server-side encryption enabled.
Add an aws_s3_bucket_server_side_encryption_configuration block.
Remediation: Add server_side_encryption_configuration block to resource
Deployment BLOCKED — critical violations must be resolved before applying.
The apply does not proceed. Nothing is created in AWS.
Add the encryption configuration:
resource "aws_s3_bucket" "secure" {
bucket = "my-secure-bucket"
}
resource "aws_s3_bucket_server_side_encryption_configuration" "secure" {
bucket = aws_s3_bucket.secure.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
Run the plan again. This time the policy check passes and you can apply.
Go to Policies & Compliance → Compliance to see:
| Severity | Behavior |
|---|---|
| Critical | Deployment blocked — cannot proceed |
| High | Warning shown — engineer must acknowledge before applying |
| Medium | Info message logged — deployment continues |
| Low | Info message logged — deployment continues |
sprintf, or forgetting to import builtins. The error message points to the problematic line.play.openpolicyagent.org) before attaching it to projects. Check that your has_encryption helper correctly traverses the Terraform plan structure.