Best Practice: Region Pinning & Jurisdiction Enforcement
Kontext
Region-Beschränkungen werden häufig dokumentiert, aber nicht technisch erzwungen. Das führt zu:
-
Unbeabsichtigten Deployments in US-Regionen durch falsche Environment-Variablen
-
Shadow-Infrastruktur in Dev-Accounts ohne Region-Guardrails
-
CI/CD-Pipelines, die Provider-Defaults verwenden
Zugehörige Controls
-
WAF-SOV-020 – Region Pinning Enforced (IaC)
Zielbild
Deployments außerhalb erlaubter Regionen sind technisch unmöglich:
-
Terraform-Validation verhindert Planung mit falscher Region
-
CI-Gate bricht den Build wenn Policy verletzt wird
-
Org-Level-Policy (SCP/Azure Policy) verhindert API-Calls auĂźerhalb erlaubter Regionen
Technische Umsetzung
Layer 1: Terraform Variable Validation
# Shared variables module (alle Repos verwenden dieses Modul)
variable "aws_region" {
type = string
description = "AWS deployment region."
validation {
condition = contains([
"eu-central-1", # Frankfurt – Primary
"eu-west-1", # Dublin – DR only
"eu-north-1", # Stockholm – optional
], var.aws_region)
error_message = "Region must be an approved sovereign EU region."
}
}
# Provider Block
provider "aws" {
region = var.aws_region
}
# FĂĽr Azure:
variable "azure_location" {
type = string
validation {
condition = contains([
"germanywestcentral",
"germanynorth",
"westeurope",
"northeurope",
"switzerlandnorth"
], var.azure_location)
error_message = "Azure location must be an approved sovereign region."
}
}
Layer 2: AWS Service Control Policy (SCP)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyOutsideApprovedRegions",
"Effect": "Deny",
"NotAction": [
"iam:*",
"sts:*",
"route53:*",
"budgets:*",
"cloudfront:*",
"waf:*",
"support:*",
"trustedadvisor:*"
],
"Resource": "*",
"Condition": {
"StringNotEquals": {
"aws:RequestedRegion": [
"eu-central-1",
"eu-west-1",
"eu-north-1"
]
},
"ArnNotLike": {
"aws:PrincipalARN": [
"arn:aws:iam::*:role/BreakGlassRole"
]
}
}
}
]
}
Layer 3: Azure Policy
{
"properties": {
"displayName": "Allowed locations for sovereign workloads",
"policyType": "Custom",
"mode": "All",
"parameters": {
"allowedLocations": {
"type": "Array",
"defaultValue": [
"germanywestcentral",
"germanynorth",
"westeurope",
"northeurope"
]
}
},
"policyRule": {
"if": {
"allOf": [
{
"field": "location",
"notIn": "[parameters('allowedLocations')]"
},
{
"field": "location",
"notEquals": "global"
}
]
},
"then": {
"effect": "deny"
}
}
}
}
Layer 4: CI/CD Check (OPA)
# policies/sovereign/region_pinning.rego
package sovereign
import rego.v1
approved_aws_regions := {
"eu-central-1",
"eu-west-1",
"eu-north-1"
}
deny contains msg if {
some resource in input.resource_changes
resource.type == "aws_instance"
not resource.change.after.availability_zone
msg := sprintf("Resource '%v' has no availability zone set", [resource.address])
}
deny contains msg if {
some provider in input.configuration.provider_config
provider.name == "aws"
not approved_aws_regions[provider.expressions.region.constant_value]
msg := sprintf("AWS provider region '%v' is not in approved sovereign list",
[provider.expressions.region.constant_value])
}
Monitoring
-
CloudTrail Alarm:
aws:RequestedRegionauĂźerhalb der genehmigten Liste -
Regelmäßige Drift-Scans mit
wafpp check --controls WAF-SOV-020 -
AWS Config Rule:
restricted-regions-policy
Typische Fehlmuster
-
„Nur für Tests": Dev/Test-Umgebungen sind oft der erste Schritt zu Production-Deployments
-
Temporäre Ausnahmen ohne Timeout: Eine befristete Ausnahme wird nie zurückgenommen
-
Shadow Projects: Neue AWS-Accounts ohne SCP-Verbindung zur Organisation