Implementing Compliance and Governance
1. Using Sentinel Policy Language
Sentinel is a policy-as-code framework integrated into HCP Terraform that enables you to enforce governance policies across your Terraform configurations. It allows you to define rules for validating infrastructure as code before deployment.
| Policy Type | Description | Use Case |
|---|---|---|
| Hard Constraints | Enforce mandatory conditions that must be met for a configuration to pass validation. | Ensure all resources have required tags or specific naming conventions. |
| Soft Constraints | Allow configurations to pass but warn about non-compliance. | Flag potential issues like unused variables or deprecated parameters. |
| Advisory Policies | Provide guidance or suggestions without blocking execution. | Suggest best practices for resource creation or configuration patterns. |
Example: Hard Constraint Policy
import "tfplan"
# Enforce that all resources must have a specific tag
main = rule {
all "aws_instance" as instance {
instance.tags contains "Environment"
}
}
Example: Soft Constraint Policy
import "tfplan"
# Warn if any resource uses a deprecated AMI
main = rule {
all "aws_instance" as instance {
if instance.ami == "ami-12345678" {
warn "Deprecated AMI used: " + instance.ami
}
}
}
Note: Sentinel policies are evaluated during the plan phase and can be enforced at different levels: organization, workspace, or project. Policies can be written in the Sentinel DSL (Domain Specific Language) which is designed for policy evaluation.
Sentinel Policy Components
- Rules: Define conditions that must or should be met.
- Imports: Bring in data from Terraform plans or state files.
- Variables: Allow dynamic input into policies for flexibility.
- Functions: Built-in functions to manipulate data and perform checks.
2. Implementing OPA Policies
| Policy Type | Description | Example |
|---|---|---|
| Rego | Policy language used by Open Policy Agent (OPA) for defining rules and constraints | |
| Constraint Template | Rego-based policy template that can be reused across different constraints | |
| Constraint | Instance of a constraint template that enforces specific rules in a given context | |
Example: Enforcing Resource Limits with OPA
package terraform
# Enforce resource limits in Terraform configurations
deny[msg] {
resource := input.resource
resource.type == "aws_instance"
resource.values.memory != nil
resource.values.memory < 2048
msg := sprintf("Memory limit must be at least 2GB, got %d", [resource.values.memory])
}
Note: OPA policies can be integrated with Terraform using the
opa provider or by running OPA as a sidecar in your CI/CD pipeline.
Warning: Ensure that OPA policies are tested thoroughly before applying them to production environments.
| Policy Enforcement Point | Description | Status |
|---|---|---|
| Pre-commit Hook | Enforce policies before committing changes to version control | NEW |
| CI/CD Pipeline | Integrate OPA checks into your CI pipeline | DEPRECATED |
| Admission Controller | Enforce policies at runtime in Kubernetes clusters | BETA |
3. Enforcing Tagging Standards
| Tag Key | Required | Description | Example Value |
|---|---|---|---|
| Environment | NEW | Environment type (dev, test, prod) | prod |
| Project | Yes | Project identifier | web-app |
| Owner | Yes | Team or individual responsible | backend-team |
| CostCenter | Yes | Financial cost center code | CC-12345 |
| Application | NEW | Application name or service | api-gateway |
Example: Tagging with Terraform
resource "aws_instance" "web_server" {
ami = "ami-12345678"
instance_type = "t3.micro"
tags = {
Environment = "prod"
Project = "web-app"
Owner = "backend-team"
CostCenter = "CC-12345"
Application = "api-gateway"
}
}
Note: Use
lifecycle rules or custom validation in CI/CD pipelines to enforce tag compliance before applying changes.
Warning: Tags must be consistent across all resources in a project to enable accurate cost allocation and resource tracking.
4. Validating Naming Conventions
| Convention | Pattern | Description | Validation |
|---|---|---|---|
| Resource Name Format | module_resource_type_name |
Enforces consistent naming across modules | ^([a-z0-9_]+_){2,}[a-z0-9_]+$ |
| Module Name Format | project_env_module |
Standardized module naming for clarity | ^[a-z0-9_]+_[a-z0-9_]+_[a-z0-9_]+$ |
| Variable Name Format | project_env_variable |
Ensures variables follow naming standards | ^[a-z0-9_]+_[a-z0-9_]+_[a-z0-9_]+$ |
Example: Naming Convention Validation
resource "aws_s3_bucket" "my_project_dev_logs" {
bucket = "my-project-dev-logs"
}
Note: Naming conventions should align with organizational standards and be validated via automated checks in CI/CD pipelines.
5. Implementing Cost Controls
| Control Type | Description | Implementation | Notes |
|---|---|---|---|
| Cost Allocation Tags | Tags used to categorize and allocate costs | {"project": "web-app", "environment": "prod"} |
Applied to resources for billing purposes |
| Budgets and Alerts | Set up budgets with alerts for cost thresholds | resource "aws_budgets_budget" { ... } |
Can be configured via AWS Console or CLI |
| Resource Limits | Enforce limits on resource usage | resource "aws_iam_role" { ... } |
Use IAM policies to restrict actions |
Example: Setting up a Cost Budget
resource "aws_budgets_budget" "monthly_cost" {
budget_type = "USAGE"
limit_amount = "1000"
limit_unit = "USD"
time_unit = "MONTHLY"
notification {
comparison_operator = "GREATER_THAN"
threshold = "80"
threshold_unit = "PERCENTAGE"
recipient_arns = ["arn:aws:sns:us-east-1:123456789012:cost-alerts"]
}
}
Note: Budgets can be set at various levels (account, OU, service) to provide granular cost control.
Warning: Alerts must be configured carefully to avoid alert fatigue. Set thresholds based on historical usage patterns.
Key Cost Control Strategies
- Use tags for cost allocation and tracking
- Implement automated alerts to notify teams of spending thresholds
- Enforce resource limits through IAM policies and constraints
- Monitor usage patterns to optimize spending
6. Enforcing Security Baselines
| Control | Description | Implementation | Notes |
|---|---|---|---|
| tfsec | Static analysis tool for Terraform files | tfsec . |
Can be integrated into CI/CD pipelines |
| checkov | Static analysis for infrastructure as code | checkov -d . |
Supports multiple IaC formats including Terraform |
| tflint | Linting tool for Terraform configurations | tflint --enable-rule=aws-* |
Highly configurable with custom rules |
Note: tfsec checks for common security misconfigurations like missing encryption or insecure network settings.
Warning: Ensure that security checks are run in a CI/CD pipeline to prevent deployment of non-compliant infrastructure.
| Rule ID | Check Name | Description | Severity |
|---|---|---|---|
| CKV_AWS_24 | Ensure that S3 bucket has encryption enabled | Checks if S3 buckets have server-side encryption | High |
| CKV_AWS_123 | Ensure that EC2 instances do not have public IP addresses | Prevents exposure of EC2 instances to the internet | High |
| CKV_AWS_124 | Ensure that security groups do not allow unrestricted ingress | Checks for open ports in security groups | High |
7. Using Policy Sets
Policy sets in Terraform Cloud and Enterprise allow you to enforce governance rules across your infrastructure as code. They define constraints on configurations, such as requiring specific tags or preventing the use of certain resources.
| Property | Description | Values | Notes |
|---|---|---|---|
| name | The name of the policy set | string |
Required field |
| description | A description of the policy set | string |
Optional field |
| enabled | Whether the policy set is enabled | true or false |
Defaults to true |
| overridable | Whether the policy set can be overridden by workspaces | true or false |
Defaults to false |
| workspace_ids | List of workspace IDs to apply the policy set to | list(string) |
Optional field |
Example: Creating a Policy Set
{
"name": "require-tags",
"description": "Enforce tag requirements on all resources",
"enabled": true,
"overridable": false,
"workspace_ids": [
"ws-1234567890"
]
}
Note: Policy sets can be managed via the Terraform Cloud UI or API. They are evaluated during plan and apply operations.
8. Testing Policies
| Component | Description | Usage |
|---|---|---|
| policy.hcl | Policy definition file using Rego syntax | Defines the policy logic and rules |
| test-policy.hcl | Test file containing test cases | Validates policy behavior with sample inputs |
| test-data.json | Sample input data for testing | Provides test scenarios with real-world data |
Example: Policy Test Case
# test-policy.hcl
package example
test_resource_access {
resource.type == "aws_s3_bucket"
resource.tags.environment == "production"
}
# Sample test data
{
"resource": {
"type": "aws_s3_bucket",
"tags": {
"environment": "production"
}
}
}
Note: Use
terraform validate to check policy syntax before running tests.
Warning: Policy tests should cover edge cases and invalid inputs to ensure robust compliance checks.
Testing Policy Best Practices
- Write tests for all policy conditions and edge cases
- Use realistic test data that mirrors production environments
- Automate policy testing in CI/CD pipelines
- Validate policies against compliance requirements
9. Auditing Policy Violations
| Policy Type | Description | Example | Compliance Status |
|---|---|---|---|
| Resource Type | Ensures only approved resource types are used | aws_instance |
NEW |
| Tagging | Enforces required tags on resources | Environment = production |
DEPRECATED |
| Region Restriction | Restricts resources to specific regions | us-west-2 |
BETA |
Example: Enforcing Tagging Policy
resource "aws_instance" "web" {
ami = "ami-12345678"
instance_type = "t2.micro"
tags = {
Environment = "production"
Project = "web-app"
}
}
Note: Terraform Cloud's policy-as-code feature allows teams to define and enforce policies across their infrastructure.
Warning: Policies must be reviewed regularly to ensure they align with organizational changes.
Policy Enforcement Summary
- Audit Logs capture all policy violations
- Automated Remediation can be configured for minor issues
- Compliance Reporting provides visibility into policy adherence
10. Implementing Custom Policies
| Policy Type | Description | Implementation Method | Example |
|---|---|---|---|
| Sentinel | Open-source policy as code framework by HashiCorp | Define policies in HCL | |
| OPA/Gatekeeper | Open Policy Agent with Kubernetes integration | Define policies in Rego | |
| Cloud Custodian | Multi-cloud policy engine for resource management | Define policies in YAML | |
Example: Terraform Sentinel Policy
import "tfplan"
policy "require-https" {
enforcement_level = "hard-mandatory"
rules = {
"require-https" = {
condition = all(aws_instance, "https", "true")
error_message = "All instances must use HTTPS"
}
}
}
Note: Sentinel policies can be enforced at different levels:
soft-mandatory, hard-mandatory, and advisory.
Warning: Hard-mandatory policies will block Terraform operations if violated.