Skip to content

KMS CMK rotation should be enabled

Cryptographic keys that remain static indefinitely increase the blast radius of a compromise. If an attacker obtains key material, every object ever encrypted under that material is exposed. Automatic rotation limits this window: after rotation, new encrypt operations use fresh material, so a leaked key version only decrypts data written during its active period.

AWS handles rotated material transparently. The same key ID continues to work for both old and new ciphertexts, so enabling rotation requires zero application changes. There is no cost increase for rotation itself. Leaving it off provides no operational benefit and silently accumulates risk.

Retrofit consideration

Rotation cannot be enabled on asymmetric keys, HMAC keys, or keys with imported key material. These key types must be rotated manually by creating new keys and re-encrypting data.

Implementation

Choose the approach that matches how you manage Terraform.

Use the compliance.tf module to enforce this control by default. See get started with compliance.tf.

module "kms" {
  source  = "pcidss.compliance.tf/terraform-aws-modules/kms/aws"
  version = ">=4.0.0"

  description = "abc123"
}

module "kms" {
  source  = "gdpr.compliance.tf/terraform-aws-modules/kms/aws"
  version = ">=4.0.0"

  description = "abc123"
}

module "kms" {
  source  = "nist80053.compliance.tf/terraform-aws-modules/kms/aws"
  version = ">=4.0.0"

  description = "abc123"
}

module "kms" {
  source  = "nistcsf.compliance.tf/terraform-aws-modules/kms/aws"
  version = ">=4.0.0"

  description = "abc123"
}

module "kms" {
  source  = "fedrampmoderate.compliance.tf/terraform-aws-modules/kms/aws"
  version = ">=4.0.0"

  description = "abc123"
}

module "kms" {
  source  = "cis.compliance.tf/terraform-aws-modules/kms/aws"
  version = ">=4.0.0"

  description = "abc123"
}

module "kms" {
  source  = "cisv80ig1.compliance.tf/terraform-aws-modules/kms/aws"
  version = ">=4.0.0"

  description = "abc123"
}

module "kms" {
  source  = "nist800171.compliance.tf/terraform-aws-modules/kms/aws"
  version = ">=4.0.0"

  description = "abc123"
}

module "kms" {
  source  = "cisacyberessentials.compliance.tf/terraform-aws-modules/kms/aws"
  version = ">=4.0.0"

  description = "abc123"
}

module "kms" {
  source  = "cisv500.compliance.tf/terraform-aws-modules/kms/aws"
  version = ">=4.0.0"

  description = "abc123"
}

module "kms" {
  source  = "cccsmedium.compliance.tf/terraform-aws-modules/kms/aws"
  version = ">=4.0.0"

  description = "abc123"
}

module "kms" {
  source  = "cfrpart11.compliance.tf/terraform-aws-modules/kms/aws"
  version = ">=4.0.0"

  description = "abc123"
}

module "kms" {
  source  = "rbicybersecurity.compliance.tf/terraform-aws-modules/kms/aws"
  version = ">=4.0.0"

  description = "abc123"
}

module "kms" {
  source  = "rbiitfnbfc.compliance.tf/terraform-aws-modules/kms/aws"
  version = ">=4.0.0"

  description = "abc123"
}

module "kms" {
  source  = "fedramplow.compliance.tf/terraform-aws-modules/kms/aws"
  version = ">=4.0.0"

  description = "abc123"
}

module "kms" {
  source  = "nistcsfv11.compliance.tf/terraform-aws-modules/kms/aws"
  version = ">=4.0.0"

  description = "abc123"
}

module "kms" {
  source  = "nist80053rev4.compliance.tf/terraform-aws-modules/kms/aws"
  version = ">=4.0.0"

  description = "abc123"
}

If you use terraform-aws-modules/kms/aws, set the right module inputs for this control. You can later migrate to the compliance.tf module with minimal changes because it is compatible by design.

module "kms" {
  source  = "terraform-aws-modules/kms/aws"
  version = ">=4.0.0"

  description = "abc123"

  enable_key_rotation = true
}

Use AWS provider resources directly. See docs for the resources involved: aws_kms_key.

resource "aws_kms_key" "this" {
  deletion_window_in_days = 7
  description             = "pofix-example-key"

  enable_key_rotation = true
}

What this control checks

This control validates that each aws_kms_key resource has enable_key_rotation = true. The argument defaults to false, so any resource that omits it or explicitly sets it to false will fail. The check applies only to symmetric encryption keys with AWS-managed key material (key_spec = "SYMMETRIC_DEFAULT" or omitted, with no imported key material). Asymmetric keys and keys with EXTERNAL origin do not support automatic rotation through this argument and are out of scope.

Common pitfalls

  • Asymmetric and HMAC keys silently ignored

    Setting enable_key_rotation = true on an asymmetric key (RSA_2048, ECC_NIST_P256, etc.) or an HMAC key produces an API error at apply time. Automatic rotation is restricted to symmetric keys with key_spec = "SYMMETRIC_DEFAULT". Those key types require manual rotation by creating a new key and reassigning aliases.

  • Imported key material not eligible

    EXTERNAL origin keys don't support automatic rotation. Setting enable_key_rotation on one throws UnsupportedOperationException at apply time. You have to manually import new material and re-encrypt dependent data.

  • Multi-Region replica keys inherit primary rotation

    Rotation for multi-region keys is controlled on the primary, not the replica. Setting enable_key_rotation on an aws_kms_replica_key has no effect. Enable it on the corresponding primary aws_kms_key instead.

  • Custom rotation periods require provider v5.36 or later

    AWS supports custom rotation periods (90 to 2560 days) via the rotation_period_in_days argument on aws_kms_key, but that argument wasn't available before Terraform AWS provider v5.36. On older versions the period defaults to 365 days regardless of what your compliance framework requires. If you need a shorter cryptoperiod, upgrade the provider and set the value explicitly.

Audit evidence

Auditors look for AWS Config results from the managed rule rotation-enabled showing all CMKs as COMPLIANT. Output from aws kms get-key-rotation-status --key-id <key-id> returning "KeyRotationEnabled": true for each in-scope key is direct point-in-time evidence. CloudTrail EnableKeyRotation API events show when rotation was activated and by whom.

For continuous assurance, a Security Hub export or a third-party compliance dashboard showing this control passing across all accounts and regions over the audit period is generally sufficient. Auditors may also request a full CMK inventory from aws kms list-keys cross-referenced with rotation status to confirm no gaps.

Framework-specific interpretation

PCI DSS v4.0: Requirement 3.6.4 says cryptographic keys must be changed at the end of their defined cryptoperiod. For KMS-encrypted cardholder data, automatic rotation is one way to satisfy that obligation, provided the rotation period aligns with your documented cryptoperiod.

GDPR: Article 32 requires appropriate technical measures to protect personal data. Rotation limits the blast radius if key material is ever disclosed, contributing to data protection by design for EU personal data stored under KMS encryption.

NIST SP 800-53 Rev 5: SC-12 and SC-12(1) require organizations to establish and manage cryptographic keys according to defined lifecycle policies, including rotation at cryptoperiod boundaries. Automatic KMS rotation satisfies that lifecycle requirement for symmetric CMKs. SC-13 is the related cryptographic protection control.

NIST Cybersecurity Framework v2.0: CSF 2.0's Protect function calls for managing data security with appropriate cryptographic safeguards. Key rotation keeps those safeguards from degrading as key material ages, which is the practical point of the outcome.

FedRAMP Moderate Baseline Rev 4: At the Moderate baseline, SC-12 and SC-13 both apply. Enabling KMS rotation is how most FedRAMP implementations satisfy the key lifecycle and cryptoperiod management requirements in those controls, though the authorizing official's documented key management policy governs the specific cryptoperiod length.

Tool mappings

Use these identifiers to cross-reference this control across tools, reports, and evidence.

  • Compliance.tf Control: kms_cmk_rotation_enabled

  • AWS Config Managed Rule: CMK_BACKING_KEY_ROTATION_ENABLED

  • Checkov Check: CKV_AWS_7

  • Powerpipe Control: aws_compliance.control.kms_cmk_rotation_enabled

  • Prowler Check: kms_cmk_rotation_enabled

  • AWS Security Hub Control: KMS.4

  • KICS Query: 22fbfeac-7b5a-421a-8a27-7a2178bb910b

  • Trivy Check: AWS-0065

Last reviewed: 2026-03-09