Terraform for AI Security: Guardrails, Model Access Control, and Threat Detection
Secure AI workloads with Terraform. Deploy Bedrock guardrails, model access IAM policies, prompt injection detection
DevOps
Implement data sovereignty and geopatriation with Terraform on AWS. Enforce data residency with SCPs, deploy region-locked infrastructure
Geopatriation — localizing data, compute, and cloud infrastructure for regulatory and resilience reasons — is a top Gartner 2026 strategic trend. Countries are increasingly requiring that certain data stays within their borders. The EU's GDPR, China's PIPL, India's DPDPA, and sector-specific regulations in finance and healthcare all drive data residency requirements.
Terraform is the ideal tool for enforcing data sovereignty because infrastructure-as-code can be audited, policy-checked, and consistently deployed to specific regions.
┌─────────────────────────────────────┐
│ AWS Organization │
│ │
│ SCP: Deny all regions except │
│ eu-central-1, eu-west-1 │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ eu-central-1 │ │ eu-west-1 │ │
│ │ (Frankfurt) │ │ (Ireland) │ │
│ │ │ │ │ │
│ │ Production │ │ DR/Backup │ │
│ │ VPC + RDS │ │ S3 Replicas │ │
│ │ + S3 │ │ │ │
│ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────┘resource "aws_organizations_policy" "eu_only" {
name = "eu-region-restriction"
type = "SERVICE_CONTROL_POLICY"
content = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "DenyNonEURegions"
Effect = "Deny"
Action = "*"
Resource = "*"
Condition = {
StringNotEquals = {
"aws:RequestedRegion" = [
"eu-central-1", # Frankfurt
"eu-west-1", # Ireland
"eu-west-2", # London
"eu-west-3", # Paris
"eu-north-1", # Stockholm
"eu-south-1", # Milan
"eu-south-2", # Spain
"eu-central-2" # Zurich
]
}
# Exempt global services
StringNotLike = {
"aws:PrincipalArn" = "arn:aws:iam::*:role/OrganizationAdmin"
}
}
},
{
Sid = "AllowGlobalServices"
Effect = "Allow"
Action = [
"iam:*",
"sts:*",
"organizations:*",
"support:*",
"budgets:*",
"waf:*",
"cloudfront:*",
"route53:*",
"health:*"
]
Resource = "*"
}
]
})
}
resource "aws_organizations_policy_attachment" "eu_only" {
policy_id = aws_organizations_policy.eu_only.id
target_id = var.eu_ou_id # Attach to EU organizational unit
}# Enforce region at the Terraform level
variable "allowed_regions" {
type = list(string)
default = ["eu-central-1", "eu-west-1"]
validation {
condition = alltrue([
for r in var.allowed_regions : can(regex("^eu-", r))
])
error_message = "Only EU regions are allowed for this deployment."
}
}
provider "aws" {
region = var.allowed_regions[0] # Primary: Frankfurt
default_tags {
tags = {
DataResidency = "EU"
Compliance = "GDPR"
ManagedBy = "Terraform"
}
}
}
provider "aws" {
alias = "dr"
region = var.allowed_regions[1] # DR: Ireland
default_tags {
tags = {
DataResidency = "EU"
Compliance = "GDPR"
}
}
}resource "aws_s3_bucket" "data" {
provider = aws
bucket = "eu-customer-data-${data.aws_caller_identity.current.account_id}"
tags = {
DataClassification = "personal-data"
DataResidency = "eu-central-1"
Regulation = "GDPR-Article-44"
}
}
# Block public access
resource "aws_s3_bucket_public_access_block" "data" {
bucket = aws_s3_bucket.data.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
# Replicate only within EU
resource "aws_s3_bucket_replication_configuration" "eu_replica" {
bucket = aws_s3_bucket.data.id
role = aws_iam_role.replication.arn
rule {
id = "eu-replication"
status = "Enabled"
destination {
bucket = aws_s3_bucket.data_replica.arn
storage_class = "STANDARD_IA"
encryption_configuration {
replica_kms_key_id = aws_kms_key.eu_west.arn
}
}
source_selection_criteria {
sse_kms_encrypted_objects {
status = "Enabled"
}
}
}
depends_on = [aws_s3_bucket_versioning.data]
}
resource "aws_s3_bucket" "data_replica" {
provider = aws.dr
bucket = "eu-customer-data-replica-${data.aws_caller_identity.current.account_id}"
tags = {
DataResidency = "eu-west-1"
Purpose = "disaster-recovery"
}
}resource "aws_kms_key" "eu_database" {
provider = aws
description = "EU-only database encryption key"
# Key cannot be shared outside EU regions
tags = {
DataResidency = "eu-central-1"
KeyPurpose = "database-encryption"
}
}
resource "aws_db_instance" "main" {
identifier = "eu-customer-db"
engine = "postgres"
engine_version = "16.3"
instance_class = "db.r6g.large"
allocated_storage = 100
storage_encrypted = true
kms_key_id = aws_kms_key.eu_database.arn
# Multi-AZ within the same region (stays in Frankfurt)
multi_az = true
# No cross-region read replicas (data stays in EU)
# Use aws_db_instance_automated_backups_replication for EU-only backup replication
deletion_protection = true
tags = {
DataResidency = "eu-central-1"
DataClassification = "personal-data"
}
lifecycle {
prevent_destroy = true
}
}Enforce data residency in CI/CD:
# policy/data-residency.rego (Open Policy Agent)
package terraform.analysis
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_s3_bucket"
# Check region from provider config
not startswith(resource.provider_name, "aws.eu")
msg := sprintf(
"S3 bucket '%s' must be deployed in an EU region for GDPR compliance",
[resource.address]
)
}
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_db_instance"
not resource.change.after.storage_encrypted
msg := sprintf(
"RDS instance '%s' must have encryption enabled for compliance",
[resource.address]
)
}module "compliance_tags" {
source = "./modules/compliance-tags"
data_residency = "EU"
regulation = "GDPR"
data_classification = "personal-data"
data_controller = var.company_name
retention_days = 2555 # 7 years
}
# modules/compliance-tags/main.tf
variable "data_residency" { type = string }
variable "regulation" { type = string }
variable "data_classification" { type = string }
variable "data_controller" { type = string }
variable "retention_days" { type = number }
output "tags" {
value = {
DataResidency = var.data_residency
Regulation = var.regulation
DataClassification = var.data_classification
DataController = var.data_controller
RetentionDays = tostring(var.retention_days)
ManagedBy = "Terraform"
LastAudit = formatdate("YYYY-MM-DD", timestamp())
}
}Data sovereignty requires enforcement at multiple layers: SCPs to restrict regions at the AWS Organizations level, Terraform provider configuration to lock deployments to specific regions, S3 replication rules that stay within allowed geographies, and OPA/Sentinel policies in CI/CD. Terraform makes these constraints auditable and repeatable — critical as geopatriation regulations expand globally in 2026.
Secure AI workloads with Terraform. Deploy Bedrock guardrails, model access IAM policies, prompt injection detection
Deploy confidential computing with Terraform on AWS. Provision Nitro Enclaves for data-in-use protection, configure KMS attestation policies
Prepare for post-quantum cryptography with Terraform. Configure hybrid TLS policies, KMS key types, ACM certificates
Build preemptive cybersecurity infrastructure with Terraform. Deploy GuardDuty, Security Hub, Inspector, Config rules