WAF++ WAF++

Best Practice: Data Residency Policy

Kontext

Data Residency Policy-Dokumente existieren häufig als PDF in einem SharePoint-Ordner – nie reviewed, nie versioniert, nie technisch abgebildet.

Das fĂĽhrt zu:

  • IaC mit Default-Regionen auĂźerhalb der erlaubten Jurisdiktion

  • Backups und Logs in nicht genehmigten Regionen

  • Inkonsistenter Tagging-Praxis, die Audits unmöglich macht

Zugehörige Controls

  • WAF-SOV-010 – Data Residency Policy Defined

  • WAF-SOV-030 – Backup Location & Retention Controlled

  • WAF-SOV-040 – Logging & Telemetry Residency Controlled

Zielbild

Eine reife Data-Residency-Policy ist:

  • Versioniert: Im gleichen Repository wie der IaC-Code

  • Vollständig: Deckt Primärdaten, Backups, Logs, Metriken, Metadaten ab

  • Technisch abgebildet: Terraform-Defaults und Variable-Validation spiegeln die Policy

  • Kontinuierlich geprĂĽft: Automatische Drift-Detection gegen Live-Infrastruktur

Technische Umsetzung

Schritt 1: Policy-Dokument strukturieren

# data-residency-policy.yml (im Repo neben Terraform-Code)
version: "2.0"
effective_date: "2025-01-01"
reviewed_by: "CISO, DPO"
next_review: "2026-01-01"

environments:
  production:
    primary_region: "eu-central-1"      # Frankfurt
    allowed_regions:
      - "eu-central-1"
      - "eu-west-1"                     # Dublin (DR only)
    forbidden_regions:
      - "us-*"
      - "ap-*"

  non_production:
    primary_region: "eu-central-1"
    allowed_regions:
      - "eu-central-1"

data_classes:
  pii:
    description: "Personenbezogene Daten (DSGVO Art. 4)"
    allowed_regions: ["eu-central-1"]
    encryption: "cmk"
    backup_retention_days: 365
    log_retention_days: 365

  financial:
    description: "Finanzdaten, Zahlungsdaten"
    allowed_regions: ["eu-central-1"]
    encryption: "cmk"
    backup_retention_days: 3650  # 10 Jahre

  operational:
    description: "Betriebsdaten, interne Logs"
    allowed_regions: ["eu-central-1", "eu-west-1"]
    encryption: "cmk"
    backup_retention_days: 90
    log_retention_days: 90

Schritt 2: IaC-Defaults aus Policy ableiten

# variables.tf – zentrales Modul für sovereign Defaults

variable "aws_region" {
  type        = string
  description = "Primary AWS deployment region. Must comply with data-residency-policy.yml."
  default     = "eu-central-1"

  validation {
    condition = contains([
      "eu-central-1",
      "eu-west-1",
      "eu-north-1",
      "eu-west-3"
    ], var.aws_region)
    error_message = <<-EOF
      Region '${var.aws_region}' is not in the approved sovereign region list.
      Approved regions: eu-central-1, eu-west-1, eu-north-1, eu-west-3.
      See: docs/data-residency-policy.yml
    EOF
  }
}

variable "data_class" {
  type        = string
  description = "Data classification for this deployment. Determines encryption and retention requirements."

  validation {
    condition     = contains(["pii", "financial", "operational", "public", "restricted"], var.data_class)
    error_message = "Invalid data-class. Must be one of: pii, financial, operational, public, restricted."
  }
}

Schritt 3: Mandatory Tagging Module

# modules/sovereign-tags/main.tf

locals {
  sovereign_tags = {
    data-residency  = var.data_residency
    data-class      = var.data_class
    environment     = var.environment
    managed-by      = "terraform"
    sovereign-scope = "true"
  }
}

variable "data_residency" {
  type = string
  validation {
    condition     = contains(["eu-only", "de-only", "ch-only", "global-approved"], var.data_residency)
    error_message = "Invalid data-residency value."
  }
}

variable "data_class" {
  type = string
}
variable "environment" {
  type = string
}

output "tags" {
  value = local.sovereign_tags
}

Schritt 4: CI-Gate fĂĽr Policy-Compliance

# .github/workflows/sovereign-checks.yml
name: Sovereign Compliance Check

on: [pull_request]

jobs:
  sovereign-policy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: WAF++ Sovereign Checks
        run: |
          # Run WAF++ checker against Terraform code
          wafpp check \
            --pillar sovereign \
            --controls WAF-SOV-010,WAF-SOV-020 \
            --path ./infrastructure \
            --fail-on violation

      - name: Validate Region Constraints
        run: |
          # OPA policy check
          opa eval \
            --input terraform.plan.json \
            --data policies/sovereign/ \
            "data.sovereign.deny"

Typische Fehlmuster

  • „Die Policy ist im Confluence": Policies, die nicht versioniert und nicht maschinenlesbar sind, können nicht in IaC-Validation eingebunden werden.

  • Fehlende Metadaten-Abdeckung: Policy deckt Primärdaten, aber nicht Logs oder Backups.

  • Veraltete Policy: Policy wurde nie reviewed; neue Services/Regionen nicht abgedeckt.

  • Inkonsistentes Tagging: Jedes Team definiert eigene Tag-Keys, automatisches Scanning unmöglich.

Metriken

  • Anteil der Data-Ressourcen mit data-residency Tag (Ziel: 100%)

  • Anteil der Data-Ressourcen mit data-class Tag (Ziel: 100%)

  • Anzahl Policy-Violations pro Sprint (Trend sollte sinken)

  • Zeit seit letztem Policy-Review (Ziel: < 12 Monate)

Reifegrad

Level 1 – Policy als PDF, nie reviewed
Level 2 – Policy versioniert im Repository, Provider-Defaults gesetzt
Level 3 – Variable Validation + mandatory Tagging + CI-Gate
Level 4 – Automatische Drift-Detection gegen Live-Infrastruktur
Level 5 – Policy-as-Code mit Auto-Remediation, vollständige Evidence-Pipeline