
August 21, 2026
10 min read
Table of Contents
By Kokil Thapa | Last reviewed: August 2026
Sentinel Policy as Code for Terraform allows engineering teams to embed compliance, security, and cost controls directly into their infrastructure provisioning workflow. Rather than relying on manual code reviews or post-deployment audits, Sentinel evaluates Terraform plans against defined rules before any changes reach production. For teams managing critical infrastructure—whether legal-tech portals handling sensitive client data or high-traffic eCommerce platforms—this automated governance layer prevents configuration drift and enforces organizational standards consistently.
How does Sentinel Policy as Code for Terraform integrate with the plan lifecycle?
Understanding where Sentinel fits in your CI/CD pipeline is critical because it operates differently than traditional linting tools. Sentinel does not scan static HCL files; instead, it inspects the structured JSON output of a terraform plan. This distinction matters because many compliance violations only become visible after interpolation, module expansion, and provider API resolution.
In practice, the evaluation happens in three distinct phases within Terraform Enterprise (TFE) or Terraform Cloud (TFC):
- Plan Generation: Terraform produces a binary plan file and its JSON representation. Sentinel never sees raw HCL; it only sees the resolved state graph.
- Policy Evaluation: Sentinel imports the
tfplan/v2module, traverses resource changes, and executes policy logic. Each policy returnstrue(pass) orfalse(fail). - Enforcement Decision: Based on the aggregate result and each policy’s enforcement level (
hard-mandatory,soft-mandatory, oradvisory), TFE/TFC either allows the run to proceed to apply or halts it immediately.
A common mistake I’ve seen on real client projects is assuming Sentinel can validate secrets or runtime behavior. It cannot. Sentinel only sees what the plan contains. If a value is marked sensitive in the plan JSON, Sentinel receives a redacted placeholder, not the actual value. Design your policies around observable attributes: tags, instance types, CIDR blocks, IAM policy documents, and resource metadata.
What are the essential Sentinel policies every Terraform team should implement first?
When introducing Sentinel Policy as Code for Terraform to an organization, start with high-value, low-friction policies that catch expensive or dangerous mistakes without generating excessive noise. Based on production experience across multiple infrastructure stacks, these four categories deliver immediate ROI:
Mandatory Tagging Enforcement
Untagged resources create cost allocation nightmares and audit failures. This policy ensures every taggable resource includes required keys like Environment, Owner, and Project:
import "tfplan/v2" as tfplan
required_tags = ["Environment", "Owner", "Project"]
taggable_resources = filter tfplan.resource_changes as _, rc {
rc.mode == "managed" and
rc.change.actions contains "create" or rc.change.actions contains "update"
}
violations = filter taggable_resources as _, rc {
tags = rc.change.after.tags else {}
missing = filter required_tags as tag {
not tags contains tag
}
length(missing) > 0
}
main = rule {
length(violations) is 0
} Prohibited Instance Types
Prevent developers from accidentally provisioning expensive GPU instances or deprecated machine types in non-production environments. This is especially relevant for Nepal-based teams managing multi-region deployments where cost sensitivity is high:
import "tfplan/v2" as tfplan
prohibited_types = ["p3.2xlarge", "p4d.24xlarge", "g5.48xlarge"]
all_instances = filter tfplan.resource_changes as _, rc {
rc.type == "aws_instance" and
(rc.change.actions contains "create" or rc.change.actions contains "update")
}
violations = filter all_instances as _, rc {
rc.change.after.instance_type in prohibited_types
}
main = rule {
length(violations) is 0
} Public S3 Bucket Prevention
Data exposure through misconfigured storage is a persistent risk. This policy blocks any S3 bucket creation or modification that enables public ACLs or bucket policies:
import "tfplan/v2" as tfplan
public_acls = ["public-read", "public-read-write"]
bucket_changes = filter tfplan.resource_changes as _, rc {
rc.type == "aws_s3_bucket" and
(rc.change.actions contains "create" or rc.change.actions contains "update")
}
acl_violations = filter bucket_changes as _, rc {
acl = rc.change.after.acl else ""
acl in public_acls
}
main = rule {
length(acl_violations) is 0
} Network Security Group Restrictions
Open ingress rules (0.0.0.0/0 on sensitive ports) are a frequent source of breaches. Restrict SSH, RDP, and database ports to known CIDR ranges:
import "tfplan/v2" as tfplan
restricted_ports = [22, 3389, 3306, 5432]
allowed_cidrs = ["10.0.0.0/8", "172.16.0.0/12"]
sg_ingress = filter tfplan.resource_changes as _, rc {
rc.type == "aws_security_group_rule" and
rc.change.after.type == "ingress" and
(rc.change.actions contains "create" or rc.change.actions contains "update")
}
violations = filter sg_ingress as _, rc {
port = rc.change.after.from_port
cidr = rc.change.after.cidr_blocks else []
(port in restricted_ports) and
any cidr as c { c == "0.0.0.0/0" }
}
main = rule {
length(violations) is 0
} For teams also managing application-level security alongside infrastructure, understanding server hardening practices complements these Sentinel policies by covering runtime configurations that IaC cannot address.
How do you structure and test Sentinel policies locally before pushing to production?
Writing Sentinel policies without local testing is like deploying untested application code. The Sentinel CLI provides a complete local development loop that mirrors TFE/TFC behavior. Here is the workflow I use on every engagement:
Step 1: Install the Sentinel CLI
Download the latest Sentinel CLI (v0.26.x as of 2026) from HashiCorp’s releases page. Verify installation:
sentinel version
# Sentinel v0.26.3 (2026) Step 2: Create Test Fixtures
Never test against live infrastructure. Generate sanitized plan JSON from representative Terraform configurations:
# Generate binary plan
terraform plan -out=tfplan.binary
# Convert to JSON for Sentinel consumption
terraform show -json tfplan.binary > mock-pass.json
# Manually edit mock-pass.json to create failure cases
cp mock-pass.json mock-fail.json
# Edit mock-fail.json: change instance_type to p3.2xlarge, remove tags, etc. Step 3: Write Sentinel Test Configuration
Create test/policy_test.hcl to define expected outcomes for each fixture:
test "enforce_instance_types_pass" {
source = "../enforce-instance-types.sentinel"
config = {
prohibited_types = ["p3.2xlarge", "p4d.24xlarge"]
}
mock = {
"tfplan/v2" = "./mock-pass.json"
}
want_result = true
}
test "enforce_instance_types_fail" {
source = "../enforce-instance-types.sentinel"
config = {
prohibited_types = ["p3.2xlarge", "p4d.24xlarge"]
}
mock = {
"tfplan/v2" = "./mock-fail.json"
}
want_result = false
} Step 4: Run Tests and Iterate
sentinel test ./test/
# PASS: enforce_instance_types_pass
# FAIL: enforce_instance_types_fail (expected false, got true)
# → Adjust policy logic, re-run until green This local loop eliminates the slow feedback cycle of pushing to TFE and waiting for runs. Commit both policies and test fixtures to version control. Treat policy tests with the same rigor as application unit tests—they are your compliance regression suite.
How does Sentinel compare to OPA/Rego and native Terraform validation?
Choosing the right policy engine depends on your team’s existing skills, infrastructure platform, and compliance requirements. Here is a practical comparison based on real-world usage across multiple client engagements:
| Criteria | Sentinel | OPA / Rego | Terraform Validation Blocks |
|---|---|---|---|
| Integration Depth | Native TFE/TFC integration; automatic plan gating | Requires external runner or TFC agent; manual wiring | Built into Terraform core; no external tooling |
| Language Complexity | Purpose-built; simpler syntax for IaC patterns | General-purpose Datalog; steeper learning curve | HCL expressions only; limited expressiveness |
| Cross-Provider Policies | Yes; import modules for AWS, Azure, GCP, K8s | Yes; provider-agnostic but requires custom data shaping | No; single-resource scope only |
| Enforcement Levels | hard-mandatory, soft-mandatory, advisory | Binary allow/deny; advisory requires wrapper logic | Error on validation failure; no warning mode |
| Licensing | BSL 1.1; free for personal/non-prod; paid for TFE/TFC | Apache 2.0; fully open source | MPL 2.0; included in Terraform OSS |
| Best For | Teams already on TFE/TFC needing tight plan integration | Multi-platform policy (K8s, CI, APIs) beyond Terraform | Simple input validation within individual modules |
If your organization uses Terraform Enterprise or Cloud exclusively and wants the path of least resistance for infrastructure governance, Sentinel is the pragmatic choice. If you need a unified policy layer across Kubernetes admission control, CI pipelines, and Terraform—and have engineers willing to invest in Rego—OPA offers broader applicability. Native validation blocks handle simple variable constraints but cannot replace external policy engines for cross-resource or organizational compliance.
For teams evaluating whether to invest in specialized DevOps tooling versus generalist development, this DevOps automation guide covers when dedicated infrastructure roles make sense versus when full-stack developers can manage policy-as-code effectively.
What are the common pitfalls when adopting Sentinel Policy as Code for Terraform in production?
After implementing Sentinel across multiple production environments, several recurring issues emerge that documentation rarely addresses:
Premature Hard-Mandatory Enforcement
Deploying new policies as hard-mandatory immediately breaks existing workflows and erodes trust. Always introduce policies as advisory first. Monitor violation frequency for 2–4 weeks. Refine rules based on real false positives. Only promote to soft-mandatory (allows override with justification) or hard-mandatory after the team understands the policy’s impact and edge cases are handled.
Neglecting Workspace and Environment Scoping
A policy that makes sense for production may be inappropriate for development sandboxes. Use TFE/TFC workspace metadata and Sentinel’s tfrun import to scope policies:
import "tfrun/v1" as tfrun
is_production = tfrun.workspace.name matches "^prod-" or
tfrun.environment == "production"
main = rule {
not is_production or length(violations) is 0
} Ignoring State Drift Between Runs
Sentinel only evaluates during explicit plan/apply operations. Manual console changes, auto-scaling events, or failed applies that partially modify resources create drift that policies never see. Enable scheduled speculative plans in TFE/TFC to run Sentinel evaluations periodically against current state, catching out-of-band modifications.
Insufficient Error Messaging
When a policy fails, the default output tells users that something violated a rule but not how to fix it. Always include descriptive error messages:
main = rule {
length(violations) is 0 else
"Violation: Resources ${violations[*].address} missing required tags. " +
"Add Environment, Owner, and Project tags per infrastructure standards."
} Implementing Sustainable Governance with Sentinel Policy as Code for Terraform
Sentinel Policy as Code for Terraform transforms infrastructure compliance from a reactive audit exercise into a proactive engineering practice embedded in daily workflows. Start with high-impact policies (tagging, instance types, public access), establish a rigorous local testing discipline, introduce enforcement levels gradually, and scope rules to avoid unnecessary friction. The goal is not perfect policy coverage on day one—it is building organizational muscle memory where compliance becomes a natural part of writing Terraform, not a gatekeeper bolted on afterward.
If your team needs help designing, testing, or operationalizing Sentinel policies—or integrating them into an existing Terraform workflow alongside application development and API-driven infrastructure automation—reach out through my contact page to discuss your specific environment and compliance requirements.

