WAF++ WAF++

Best Practice: Key Sovereignty

Kontext

Standard-Verschlüsselung (AES256/SSE-S3) verwendet Provider-Managed Keys. Der Cloud-Anbieter verwaltet das Schlüsselmaterial und kann theoretisch auf verschlüsselte Daten zugreifen – oder gesetzlich dazu verpflichtet werden.

Für sensitive Daten (PII, Finanzen, Gesundheit) ist dies keine Souveränitätsgarantie.

Zugehörige Controls

Zielbild

Eine reife Key-Sovereignty-Implementierung bietet:

  • Klare Schlüssel-Hierarchie nach Datenkritikalität

  • Automatische Rotation für alle CMKs

  • Prozessgesteuerte Deletion mit Schutzfrist

  • Monitoring aller Schlüsselzugriffe auf Anomalien

Technische Umsetzung

AWS KMS – Customer Managed Key

# modules/kms-sovereign/main.tf

resource "aws_kms_key" "sovereign_data" {
  description             = "Sovereign data encryption key for ${var.data_class} data"
  key_usage               = "ENCRYPT_DECRYPT"
  customer_master_key_spec = "SYMMETRIC_DEFAULT"

  # Key rotation – mandatory für alle CMKs
  enable_key_rotation = true

  # Deletion Window: Zeit für Review vor endgültiger Löschung
  deletion_window_in_days = 30

  # Restrict key usage to specific services and principals
  policy = data.aws_iam_policy_document.kms_policy.json

  tags = {
    data-class     = var.data_class
    data-residency = var.data_residency
    environment    = var.environment
    managed-by     = "terraform"
  }
}

# Tight Key Policy
data "aws_iam_policy_document" "kms_policy" {
  # Root account can manage the key (required)
  statement {
    sid     = "Enable Root Account Management"
    effect  = "Allow"
    principals {
      type        = "AWS"
      identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"]
    }
    actions   = ["kms:*"]
    resources = ["*"]
  }

  # Specific services can use the key for encryption
  statement {
    sid    = "Allow S3 Service Encryption"
    effect = "Allow"
    principals {
      type        = "Service"
      identifiers = ["s3.amazonaws.com"]
    }
    actions = [
      "kms:GenerateDataKey*",
      "kms:Decrypt"
    ]
    resources = ["*"]
    condition {
      test     = "StringEquals"
      variable = "kms:ViaService"
      values   = ["s3.${var.aws_region}.amazonaws.com"]
    }
  }
}

resource "aws_kms_alias" "sovereign_data" {
  name          = "alias/${var.environment}-${var.data_class}-sovereign"
  target_key_id = aws_kms_key.sovereign_data.key_id
}

S3 mit CMK

resource "aws_s3_bucket_server_side_encryption_configuration" "sovereign" {
  bucket = aws_s3_bucket.data.id

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm     = "aws:kms"
      kms_master_key_id = aws_kms_key.sovereign_data.arn
    }
    # Reduces API calls and cost by using bucket-level key wrapping
    bucket_key_enabled = true
  }
}

RDS mit CMK

resource "aws_db_instance" "sovereign" {
  identifier        = "sovereign-db-${var.environment}"
  engine            = "postgres"
  instance_class    = "db.t3.medium"

  # Mandatory: encrypted with CMK
  storage_encrypted = true
  kms_key_id        = aws_kms_key.sovereign_data.arn

  # Backup within sovereign region
  backup_retention_period = 30

  # Prevent accidental deletion
  deletion_protection = true
}

Azure Key Vault mit Purge Protection

resource "azurerm_key_vault" "sovereign" {
  name                = "kv-sovereign-${var.environment}"
  location            = var.azure_location
  resource_group_name = azurerm_resource_group.main.name
  sku_name            = "premium"  # HSM-backed keys

  # Required for sovereignty: prevent accidental key deletion
  purge_protection_enabled   = true
  soft_delete_retention_days = 90

  # RBAC authorization (not access policies)
  enable_rbac_authorization = true

  network_acls {
    default_action             = "Deny"
    bypass                     = ["AzureServices"]
    virtual_network_subnet_ids = [azurerm_subnet.private.id]
  }

  tags = {
    data-class     = var.data_class
    data-residency = "eu-only"
    environment    = var.environment
  }
}

Schlüssel-Hierarchie nach Datenkritikalität

Datenklasse Key-Typ Provider Rotation

Public

PMK (AES256)

Cloud-Provider

Automatisch (Provider)

Operativ/Intern

CMK

Cloud-KMS (AWS KMS / Azure Key Vault)

Automatisch (jährlich)

PII / Personal

CMK (Minimum) oder BYOK

Cloud-KMS mit tight Policy

Automatisch + manuelles Review

Finanzen / Gesundheit

BYOK oder HYOK

CloudHSM / Azure Dedicated HSM

Manuell (Key Ceremony)

KMS Monitoring (CloudTrail + CloudWatch)

# Alarm: Key deletion scheduled
resource "aws_cloudwatch_metric_alarm" "kms_key_deletion" {
  alarm_name          = "kms-key-scheduled-deletion-${var.environment}"
  comparison_operator = "GreaterThanOrEqualToThreshold"
  evaluation_periods  = "1"
  metric_name         = "NumberOfKMSKeysScheduledForDeletion"
  namespace           = "AWS/KMS"
  period              = "60"
  statistic           = "Sum"
  threshold           = "1"
  alarm_description   = "KMS key scheduled for deletion – requires immediate review"
  alarm_actions       = [aws_sns_topic.security_alerts.arn]
}

Typische Fehlmuster

  • AES256 für PII: Provider-Managed Keys für sensitive Daten – keine Souveränitätsgarantie

  • KMS Rotation disabled: Erhöhtes Risiko bei Key-Kompromittierung

  • Kein Deletion Window: Keys können sofort gelöscht werden, ohne Review

  • Zu weite Key Policy: Key kann von allen IAM-Prinzipalen verwendet werden

Metriken

  • Anteil PII/Finanzdaten-Ressourcen mit CMK (Ziel: 100%)

  • Anteil KMS Keys mit enable_key_rotation = true (Ziel: 100%)

  • Anteil Keys mit deletion_window_in_days >= 14 (Ziel: 100%)

  • Anzahl ungeplanter Key-Deletion-Events pro Quartal

Reifegrad

Level 1 – Alles PMK
Level 2 – CMK für sensitive Daten
Level 3 – Kein PMK für PII/Finanzen; Rotation aktiv; Key-Policy tight
Level 4 – BYOK für kritische Daten; KMS Access Monitoring; Anomalie-Erkennung
Level 5 – HYOK mit externem HSM; Cryptographic Erasure getestet; Key Ceremonies dokumentiert