WAF-SEC-030 – Encryption at Rest with CMK

Beschreibung

All data stores containing sensitive or classified data MUST be encrypted at rest using customer-managed keys (CMK) stored in AWS KMS. Automatic key rotation MUST be enabled for all CMKs. Encryption using only provider-managed keys (SSE-S3/AES256) is NOT sufficient for sensitive, PII, financial, or regulated data. KMS key deletion windows MUST be set to a minimum of 7 days. KMS key policies MUST restrict access to explicitly authorized principals only.

Begründung

Risiko Beschreibung

Risk

Sensitive data is exposed if storage or transport lacks strong encryption.

Risk

Compromised keys or weak key rotation extend the blast radius of a breach.

Anforderungen

  • All data stores containing sensitive or classified data MUST be encrypted at rest using customer-managed keys (CMK) stored in AWS KMS.

  • Automatic key rotation MUST be enabled for all CMKs.

  • KMS key deletion windows MUST be set to a minimum of 7 days.

  • KMS key policies MUST restrict access to explicitly authorized principals only.

Implementierungsleitfaden

  1. Implement the required configuration as code in Terraform or equivalent IaC.

  2. Add an automated check to CI/CD so deviations are caught before deployment.

Reifegrade

Level Name Kriterien

L1

Ad hoc – control not consistently applied

* Manual evidence exists for some workloads, but coverage is unknown.

L2

Standardised – policy defined and communicated

* A version-controlled policy, ADR, or standard describes the requirement.

L3

Integrated – automated validation in CI/CD

* Terraform checks run automatically on pull requests and report results.

L4

Auditable – metrics and exceptions tracked

* Control coverage, failures, and approved exceptions are reported quarterly.

L5

Optimised – continuous improvement based on data

* Control effectiveness is measured and iteratively improved.

Checks

waf-sec-030.tf.aws.rds-encryption-enabled

Engine: terraform | Provider: aws | Automated: Ja

RDS instances and clusters must be encrypted at rest with a CMK

All RDS database instances and Aurora clusters must have storage_encrypted = true and must reference a customer-managed KMS key via kms_key_id.

Scope: resource — aws_db_instance, aws_rds_cluster

Assertions: * storage_encrypted is true — RDS instance/cluster must have storage encryption enabled (storage_encrypted = true). * kms_key_id attribute exists — RDS instance/cluster must use a customer-managed KMS key (kms_key_id must be set).

Remediation: Set storage_encrypted = true and kms_key_id = aws_kms_key.rds_key.arn on the aws_db_instance or aws_rds_cluster resource. Note: enabling encryption on an existing unencrypted RDS instance requires creating an encrypted snapshot and restoring to a new instance. Plan for a maintenance window.

Compliant
resource "aws_kms_key" "rds" {
  description             = "CMK for RDS encryption"
  enable_key_rotation     = true
  deletion_window_in_days = 30
}
resource "aws_db_instance" "main" {
  identifier        = "app-db-prod"
  engine            = "postgres"
  instance_class    = "db.t3.medium"
  storage_encrypted = true
  kms_key_id        = aws_kms_key.rds.arn
  # ... other required attributes
}
Non-Compliant
resource "aws_db_instance" "main" {
  identifier        = "app-db-prod"
  engine            = "postgres"
  instance_class    = "db.t3.medium"
  storage_encrypted = false  # WAF-SEC-030 violation
  # kms_key_id not set – using default AWS-managed key
}

waf-sec-030.tf.aws.kms-key-rotation

Engine: terraform | Provider: aws | Automated: Ja

KMS keys must have automatic rotation enabled and a sufficient deletion window

All customer-managed KMS keys must have enable_key_rotation = true and deletion_window_in_days >= 7 to ensure keys are regularly rotated and accidental deletion can be recovered.

Scope: resource — aws_kms_key

Assertions: * enable_key_rotation is true — KMS key must have automatic rotation enabled (enable_key_rotation = true). * deletion_window_in_days greater than or equal 7 — KMS key deletion window must be at least 7 days to allow recovery from accidental deletion.

Remediation: Set enable_key_rotation = true on all aws_kms_key resources. Set deletion_window_in_days to at least 7 (recommend 30 for production keys). Note: key rotation does not apply to asymmetric keys or keys in external key stores; those require separate rotation procedures.

Compliant
resource "aws_kms_key" "app_data" {
  description             = "CMK for application data encryption"
  enable_key_rotation     = true
  deletion_window_in_days = 30
  tags = {
    owner       = "platform-team"
    environment = "production"
  }
}
Non-Compliant
resource "aws_kms_key" "app_data" {
  description             = "CMK for application data"
  enable_key_rotation     = false   # WAF-SEC-030 violation
  deletion_window_in_days = 3       # WAF-SEC-030 violation: below 7-day minimum
}

waf-sec-030.tf.azurerm.key-vault-key-expiration

Engine: terraform | Provider: azurerm | Automated: Ja

Azure Key Vault keys used for encryption must have an expiration date

All azurerm_key_vault_key resources that protect sensitive data must have expiration_date set to enforce key lifecycle and rotation.

Scope: resource — azurerm_key_vault_key

Assertions: * expiration_date attribute exists — Key Vault key must have an expiration_date for lifecycle management.

Remediation: Set expiration_date on every azurerm_key_vault_key resource used for workload encryption. Establish a key rotation process that refreshes keys before expiration.

Compliant
resource "azurerm_key_vault_key" "app" {
  name         = "app-encryption-key"
  key_vault_id = azurerm_key_vault.main.id
  key_type     = "RSA"
  key_size     = 2048
  expiration_date = "2026-01-01T00:00:00Z"
}
Non-Compliant
resource "azurerm_key_vault_key" "app" {
  name         = "app-encryption-key"
  key_vault_id = azurerm_key_vault.main.id
  key_type     = "RSA"
  key_size     = 2048
  # expiration_date not set
}

waf-sec-030.tf.azurerm.key-vault-purge-protection

Engine: terraform | Provider: azurerm | Automated: Ja

Azure Key Vault must have purge protection and soft delete enabled

All azurerm_key_vault resources must have purge_protection_enabled = true and soft_delete_retention_days >= 7 to protect against accidental or malicious key destruction.

Scope: resource — azurerm_key_vault

Assertions: * purge_protection_enabled is true — Key Vault purge protection must be enabled. * soft_delete_retention_days greater than or equal 7 — Key Vault soft delete retention must be at least 7 days.

Remediation: Set purge_protection_enabled = true and soft_delete_retention_days to at least 7 on every azurerm_key_vault resource that stores workload keys.

Compliant
resource "azurerm_key_vault" "main" {
  name                        = "workload-keyvault"
  location                    = azurerm_resource_group.main.location
  resource_group_name         = azurerm_resource_group.main.name
  tenant_id                   = data.azurerm_client_config.current.tenant_id
  sku_name                    = "standard"
  soft_delete_retention_days  = 7
  purge_protection_enabled    = true
}
Non-Compliant
resource "azurerm_key_vault" "main" {
  name                        = "workload-keyvault"
  location                    = azurerm_resource_group.main.location
  resource_group_name         = azurerm_resource_group.main.name
  tenant_id                   = data.azurerm_client_config.current.tenant_id
  sku_name                    = "standard"
  # purge_protection_enabled defaults to false
}

waf-sec-030.tf.google.sql-cmek-encryption

Engine: terraform | Provider: google | Automated: Ja

Cloud SQL instances must be encrypted with a customer-managed key

All google_sql_database_instance resources must reference a customer-managed encryption key via encryption_key_name.

Scope: resource — google_sql_database_instance

Assertions: * settings.encryption_key_name attribute exists — Cloud SQL instance must use a customer-managed encryption key (CMEK).

Remediation: Set encryption_key_name to a Cloud KMS key for every google_sql_database_instance that stores sensitive or regulated data.

Compliant
resource "google_sql_database_instance" "main" {
  name             = "app-db"
  database_version = "POSTGRES_15"
  region           = "europe-west3"
  settings {
    tier = "db-custom-2-7680"
    encryption_key_name = google_kms_crypto_key.db_key.id
  }
}
Non-Compliant
resource "google_sql_database_instance" "main" {
  name             = "app-db"
  database_version = "POSTGRES_15"
  region           = "europe-west3"
  settings {
    tier = "db-custom-2-7680"
    # encryption_key_name not set – uses Google-managed key
  }
}

waf-sec-030.tf.google.kms-key-rotation

Engine: terraform | Provider: google | Automated: Ja

Cloud KMS keys must have a rotation period configured

All google_kms_crypto_key resources must have rotation_period set to enforce regular key rotation.

Scope: resource — google_kms_crypto_key

Assertions: * rotation_period attribute exists — Cloud KMS key must have a rotation_period configured.

Remediation: Set rotation_period (e.g., "7776000s" for 90 days) on every google_kms_crypto_key resource used for workload encryption.

Compliant
resource "google_kms_crypto_key" "app" {
  name            = "app-key"
  key_ring        = google_kms_key_ring.app.id
  rotation_period = "7776000s"
}
Non-Compliant
resource "google_kms_crypto_key" "app" {
  name     = "app-key"
  key_ring = google_kms_key_ring.app.id
  # rotation_period not set
}

waf-sec-030.tf.stackit.resource-encryption-enabled

Engine: terraform | Provider: stackit | Automated: Ja

STACKIT managed resources must use encryption at rest

STACKIT resources that store data (e.g., stackit_postgres_flex_instance, stackit_redis_instance, stackit_opensearch_instance, stackit_mysql_instance) must have encryption at rest enabled or use a customer-managed key where supported.

Scope: resource — stackit_postgres_flex_instance, stackit_mysql_instance, stackit_redis_instance, stackit_opensearch_instance, stackit_object_storage_bucket

Assertions: * name attribute exists — STACKIT data resource must be defined with encryption at rest enabled by default or explicitly configured.

Remediation: Enable encryption at rest on all STACKIT managed data services. Use customer-managed keys via stackit_object_storage_bucket or service-specific encryption settings where available.

Compliant
resource "stackit_postgres_flex_instance" "app" {
  project_id = var.stackit_project_id
  name       = "app-db"
  version    = "15"
  # encryption enabled by default; CMK configured via STACKIT console/API
}
Non-Compliant
resource "stackit_postgres_flex_instance" "app" {
  project_id = var.stackit_project_id
  name       = "app-db"
  # WAF-SEC-030 violation: encryption not verified or disabled
}

waf-sec-030.config.ovh.ovh-identity-access

Engine: config | Provider: ovh | Automated: Ja

OVHcloud data services must have encryption at rest enabled and documented

A version-controlled policy document must exist at docs/security/waf-sec-030-ovh-identity-access.md and document the OVHcloud implementation of this control. The checker validates that the file exists and contains a normative requirement statement (MUST/SHALL/required/mandatory).

Scope: file — docs/security/waf-sec-030-ovh-identity-access.md

Assertions: * content matches pattern (?i)MUST|SHALL|required|mandatory|enforced|documented — Policy file docs/security/waf-sec-030-ovh-identity-access.md must contain a normative requirement statement.

Remediation: Create or update docs/security/waf-sec-030-ovh-identity-access.md. State the requirement, how it is implemented for OVHcloud, the review cadence, and the owner.

Compliant
docs/security/waf-sec-030-ovh-identity-access.md:
- The OVHcloud implementation of WAF-SEC-030 is documented.
- Implementation status and owner are recorded.
- Review cadence is defined (e.g. quarterly).
Non-Compliant
# `docs/security/waf-sec-030-ovh-identity-access.md` is missing or does not contain a normative requirement.
# WAF-SEC-030 violation: OVHcloud control is not documented

waf-sec-030.tf.hcloud.volume-encryption

Engine: terraform | Provider: hcloud | Automated: Ja

Hetzner Cloud volumes must be encrypted at rest

All hcloud_volume resources attached to production servers must use Hetzner Cloud encryption at rest. Validate via the resource definition or a documented standard.

Scope: resource — hcloud_volume

Assertions: * name attribute exists — Hetzner Cloud volume must exist and have encryption at rest enabled or documented.

Remediation: Create hcloud_volume resources with encryption enabled. For operating-system-level encryption, document LUKS/dm-crypt configuration in a version-controlled standard.

Compliant
resource "hcloud_volume" "app" {
  name      = "app-data"
  size      = 100
  server_id = hcloud_server.app.id
  format    = "ext4"
  # Hetzner Cloud volume encryption at rest is enabled by default for new volumes
}
Non-Compliant
resource "hcloud_volume" "app" {
  name      = "app-data"
  size      = 100
  server_id = hcloud_server.app.id
  # WAF-SEC-030 violation: encryption at rest not verified
}

Evidenz

Art Erforderlich Beschreibung

iac

Erforderlich

Terraform configuration implementing the control.

governance

Erforderlich

Policy, ADR, or standard documenting the requirement.

config

Optional

Cloud console or API output confirming runtime state.

Verwandte Controls

Framework Controls

ISO 27001:2022

* A.8.24 – Use of cryptography * A.5.10 – Acceptable use of information

ISO 27017

* CLD.10.1 – Cryptographic controls in cloud services

ISO 27018

* A.10.1 – Cryptographic controls for PII protection

CIS Controls v8

* CIS 3.11 – Encrypt sensitive data at rest

CSA STAR

* CCM CEK-01 – Encryption and Key Management Policy * CCM CEK-03 – Data Encryption

PCI DSS v4.0

* Req 3.5 – Cryptographic keys protection * Req 3.6 – Encryption of stored cardholder data

SOC 2 Type II

* CC6.1 – Logical access security * C1.1 – Confidentiality of information

GDPR

* Art. 32 – Security of processing (encryption) * Art. 25 – Data protection by design and by default

NIS2

* Art. 21(2)(h) – Cryptography and encryption policies

DORA

* Art. 9 – Protection and prevention

EUCS (ENISA)

* CKM-01 – Cryptographic policy * CKM-02 – Key management

BSI C5:2020

* CRY-01 – Use of cryptography * CRY-02 – Key management * CRY-03 – Encryption of stored data

IT-Grundschutz

* CON.1 – Kryptokonzept * SYS.1.5 – Speichersysteme

TISAX

* Information security – Cryptographic protection of information

ANSSI SecNumCloud

* Domain – Cryptography and key management

BIO

* BIO – Cryptografische maatregelen

ENS High

* mp.info.3 – Cifrado

UK NCSC CAF

* B3.d – Data at rest – encryption

UK GDPR

* Art. 32 – Security of processing

NIST SP 800-53

* SC-12 – Cryptographic Key Establishment and Management * SC-13 – Cryptographic Protection * SC-28 – Protection of Information at Rest

NIST CSF 2.0

* PR.DS-01 – Data-at-rest is protected

FedRAMP

* SC-12, SC-13, SC-28 (Moderate/High baseline)

HIPAA

* § 164.312(a)(2)(iv) – Encryption and decryption of ePHI

CMMC 2.0

* SC.L2-3.13.11 – Employ FIPS-validated cryptography * SC.L2-3.13.16 – Protect confidentiality of CUI at rest

IRAP

* ISM – Cryptography

CCCS PBMM

* SC-12, SC-13, SC-28 – Cryptographic protection

MAS TRM

* Ch.11 – Cryptography

ISMAP

* Cryptographic controls

FISC

* Technical measures – Encryption of stored data