Terraform Policy-as-Code (Sentinel / OPA / Checkov) Prompt
Implement policy-as-code for Terraform — Sentinel (TFC), OPA/Conftest, Checkov, tfsec, enforce security and compliance.
- Target user
- Platform / security engineers enforcing policy
- Difficulty
- Advanced
- Tools
- Claude, ChatGPT
The prompt
You are a senior security engineer who has implemented policy-as-code for Terraform — Sentinel for TFC, OPA for self-hosted, Checkov for general. I will provide: - Policy goals (security, cost, compliance) - Current CI/CD - Tool preference Your job: 1. **Tool comparison**: - **Sentinel** — TFC-native; HCL-like; deep TF integration - **OPA / Conftest** — open source; Rego; works anywhere - **Checkov** — opinionated rules; Python; many providers - **tfsec** / **trivy** — security-focused; quick 2. **For policy categories**: - **Security** — no public S3, encrypted volumes, MFA - **Cost** — instance type caps, region restrictions - **Compliance** — tagging mandatory, region allowlist - **Reliability** — backup enabled, multi-AZ 3. **For OPA / Conftest**: - Policies in Rego - Run against plan JSON - Per-resource checks 4. **For Sentinel**: - TFC platform - Soft-mandatory / hard-mandatory enforcement - tfplan / tfstate / tfconfig 5. **For Checkov**: - Out-of-box rules - Custom Python - SARIF output for GitLab 6. **For pipeline integration**: - Run after plan, before apply - Block merge on violation - Soft warnings for non-critical 7. **For exceptions**: - Explicit, documented - Time-bounded - Auditable 8. **For policy testing**: - Unit tests on policies - Fixture inputs - Verify rules catch what they should Mark DESTRUCTIVE: removing policy in production without alternative, policy bypass for "emergency" never reviewed, false positive suppression hiding real issues. --- Policy goals: [DESCRIBE] Current CI/CD: [DESCRIBE] Tool preference: [DESCRIBE]
Why this prompt works
Policy is governance at scale. This prompt walks tools.
How to use it
- Pick tool matching platform.
- Start with security policies.
- Soft-warn first, then hard.
- Audit exceptions.
Patterns
OPA / Conftest
# policies/aws_s3.rego
package main
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_s3_bucket"
resource.change.actions[_] == "create"
not resource.change.after.server_side_encryption_configuration
msg := sprintf("S3 bucket %s is created without encryption", [resource.address])
}
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_s3_bucket_public_access_block"
resource.change.actions[_] == "create"
resource.change.after.block_public_acls == false
msg := sprintf("S3 public access not blocked: %s", [resource.address])
}
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_instance"
not contains_required_tags(resource.change.after.tags)
msg := sprintf("Instance %s missing required tags", [resource.address])
}
contains_required_tags(tags) {
tags["Environment"]
tags["Owner"]
tags["CostCenter"]
}
# Generate plan JSON
terraform plan -out=tfplan
terraform show -json tfplan > plan.json
# Run conftest
conftest test plan.json --policy policies/
Sentinel (TFC)
# policies/no-public-s3.sentinel
import "tfplan/v2" as tfplan
s3_buckets = filter tfplan.resource_changes as _, rc {
rc.type is "aws_s3_bucket" and rc.change.actions contains "create"
}
violators = filter s3_buckets as addr, rc {
rc.change.after.acl is "public-read" or rc.change.after.acl is "public-read-write"
}
main = rule {
length(violators) is 0
}
# sentinel.hcl (policy set config)
policy "no-public-s3" {
source = "./policies/no-public-s3.sentinel"
enforcement_level = "hard-mandatory"
}
policy "mandatory-tags" {
source = "./policies/mandatory-tags.sentinel"
enforcement_level = "soft-mandatory"
}
Checkov
# .checkov.yaml
download-external-modules: true
quiet: true
soft-fail: false
skip-check:
- CKV_AWS_19 # specific exemption with reason
# Run
checkov -d . --output cli --output gitlab-sast --output-file-path checkov-results.json
# Custom rule
# In custom_checks/
# custom_checks/MyOrgTaggingCheck.py
from checkov.common.models.enums import CheckResult, CheckCategories
from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck
class MyOrgRequiredTags(BaseResourceCheck):
def __init__(self):
super().__init__(
name="My Org tagging policy",
id="CKV_MYORG_1",
categories=[CheckCategories.GENERAL_SECURITY],
supported_resources=["aws_instance", "aws_s3_bucket", "aws_rds_cluster"],
)
def scan_resource_conf(self, conf):
tags = conf.get("tags", [{}])[0]
required = ["Environment", "Owner", "CostCenter"]
for tag in required:
if tag not in tags:
return CheckResult.FAILED
return CheckResult.PASSED
check = MyOrgRequiredTags()
tfsec / trivy
# tfsec
tfsec . --format gitlab-sast --out tfsec-results.json
# trivy (replaced tfsec)
trivy config .
CI integration (GitLab)
policy-check:
stage: policy
needs: [plan]
image: bridgecrew/checkov:latest
script:
- checkov -d . --output gitlab-sast --output-file-path gl-sast-report.json
artifacts:
reports:
sast: gl-sast-report.json
allow_failure: false # block merge on violation
opa-policy-check:
stage: policy
needs: [plan]
image: openpolicyagent/conftest:latest
script:
- terraform show -json tfplan > plan.json
- conftest test plan.json --policy policies/
Common findings this catches
- No policy enforcement → start with Checkov.
- Public S3 buckets → block.
- Missing tags → mandatory tagging.
- Cost policy not enforced → instance type limits.
- Soft-fail in production → harden.
- No audit of exceptions → require justification.
- Stale rules → review quarterly.
When to escalate
- Cross-team policy ownership — coordinate.
- Compliance officer requirements — security.
- Performance impact at scale — tune.
Related prompts
-
Infrastructure as Code Security Review Prompt
AI security review of Terraform, CloudFormation, or Helm charts — surface dangerous defaults, missing encryption, overly-permissive IAM, and exposed services.
-
Terraform CI/CD: Atlantis, Cloud, GitOps Prompt
Choose and configure Terraform CI/CD — Atlantis, Terraform Cloud, Spacelift, custom CI; plan/apply workflows, approvals.
-
Dangerous Terraform Changes Review Prompt
Scan a `terraform plan` output for changes that will silently destroy data, cause outages, or trigger irreversible mutations.