In regulated industries (finance, healthcare), infrastructure IS compliance. Your database encryption key, VPC isolation, audit logging — these aren’t nice-to-haves, they’re mandatory controls.
Most teams manually configure these in the console, which is:
Terraform solves this by turning compliance requirements into code.
Instead of writing a Terraform file for “deploy a database,” write a module for “deploy a SOC 2-compliant database.”
# modules/secure-database/main.tf
variable "environment" {
type = string
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Environment must be dev, staging, or prod."
}
}
resource "google_sql_database_instance" "main" {
name = "db-${var.environment}"
database_version = "POSTGRES_15"
# SOC 2 requirement: Encryption at rest
settings {
backup_configuration {
enabled = true
point_in_time_recovery_enabled = true
backup_retention_days = var.environment == "prod" ? 30 : 7
}
# SOC 2 requirement: No public IP
ip_configuration {
require_ssl = true
private_network = google_compute_network.private.id
authorized_networks = [] # No public access
enable_private_path_length_check = true
}
# ISO 27001 requirement: Database audit logging
database_flags {
name = "log_checkpoints"
value = "on"
}
database_flags {
name = "log_connections"
value = "on"
}
database_flags {
name = "log_statement"
value = "all" # Audit every statement
}
}
# Deletion protection (prevents accidents in prod)
deletion_protection = var.environment == "prod" ? true : false
}
# PCI-DSS requirement: Encrypt data at rest
resource "google_kms_crypto_key" "database" {
name = "database-key-${var.environment}"
lifecycle {
prevent_destroy = true # Never delete the key (audit requirement)
}
}
# ISO 27001 requirement: Monitor access
resource "google_monitoring_alert_policy" "database_access" {
display_name = "Database access anomaly"
combiner = "OR"
conditions {
display_name = "Unusual connection count"
condition_threshold {
filter = "resource.type=\"cloudsql_database\" AND metric.type=\"cloudsql.googleapis.com/database/network/connections\""
threshold_value = 1000
comparison = "COMPARISON_GT"
}
}
notification_channels = [google_monitoring_notification_channel.security_team.id]
}
Usage:
# environments/prod/main.tf
module "database" {
source = "../../modules/secure-database"
environment = "prod"
}
When you terraform apply, you’re applying compliance as code.
Terraform has state files. These are your compliance proof.
# terraform.tfstate (simplified)
{
"resources": [{
"type": "google_sql_database_instance",
"name": "main",
"instances": [{
"attributes": {
"database_version": "POSTGRES_15",
"settings": {
"backup_configuration": {
"backup_retention_days": 30
},
"database_flags": [
{"name": "log_statement", "value": "all"}
]
}
}
}]
}]
}
When an auditor asks, “Prove your database has audit logging enabled,” you show them:
$ terraform show | grep log_statement
"log_statement" = "all"
Proof in < 1 second.
Use Sentinel (HashiCorp’s policy language) to block non-compliant Terraform plans:
# policies/require-encryption.sentinel
import "tfplan/v2" as tfplan
# Ensure all databases have encryption enabled
databases = filter tfplan.resource_changes as _, rc {
rc.type == "google_sql_database_instance"
}
encryption_enabled = rule {
all databases as _, db {
db.change.after.settings[0].backup_configuration[0].location != null
}
}
main = rule {
(length(databases) == 0) or encryption_enabled
}
When someone tries to deploy a database without encryption:
$ terraform apply
Error: Policy violation: require-encryption
Databases must have backup encryption enabled.
Tags: #Terraform #Compliance #IaC #SOC2 #ISO27001 #Regulated
Published: June 2026
Author: Pratik Dhanave
Related Projects: Bloom (Standard Chartered), regulated fintech