Back to blog
AWSBest PracticesCloud SecurityIdentity & AccessOperations & Compliance

KMS Key Rotation Disabled: Why It Matters and How to Fix It

Learn why disabled KMS key rotation is a security and compliance risk, plus CLI, Terraform, and policy-as-code steps to enable automatic rotation in AWS.

TL;DR

This check flags customer-managed KMS keys that do not have automatic annual key rotation turned on. Long-lived encryption keys widen your blast radius if material is ever compromised. Fix it with aws kms enable-key-rotation --key-id <key-id>.

Encryption keys are not the kind of thing you set once and forget. The longer a single key encrypts your data, the more data is sitting behind one piece of cryptographic material, and the worse your day gets if that material ever leaks. AWS KMS gives you a low-effort way to limit that exposure: automatic key rotation. This check catches customer-managed keys where that safety net is switched off.


What this check detects

The account_kmskeyrotation check inspects every customer-managed KMS key (CMK) in your account and reports any key where automatic rotation is disabled. When rotation is enabled, KMS generates new cryptographic material for the key on a recurring schedule (annually by default, and configurable down to 90 days on newer keys) while keeping the same key ID and ARN.

It is worth being precise about what rotation does and does not change:

  • The key ID, ARN, alias, and key policy stay the same.
  • KMS creates fresh backing key material and uses it for all new encrypt operations.
  • Old key material is retained so that data already encrypted with it can still be decrypted.
  • Your application code does not change. Rotation is fully transparent.

Note: This check applies only to symmetric customer-managed keys. AWS-managed keys (the ones with aws/ aliases like aws/s3) rotate automatically and you cannot change that. Asymmetric keys, HMAC keys, and keys with imported material do not support automatic rotation, so they are out of scope.


Why it matters

Key rotation is a core principle of cryptographic hygiene, and most compliance frameworks expect it. PCI DSS, NIST 800-57, SOC 2, and CIS AWS Foundations Benchmark control 3.8 all call for periodic rotation of encryption keys. A flag on this check is a common audit finding.

The security argument is about limiting blast radius. Consider a few scenarios:

  • Compromised key material. If an attacker somehow obtains the backing key material, or if a subtle flaw is found in how it was generated, every byte ever encrypted under that key is exposed. Rotation caps the amount of data tied to any single piece of material.
  • Insider risk and credential leaks. Long-lived keys mean a single leaked set of credentials with kms:Decrypt can unlock years of accumulated data. Rotation does not prevent the decrypt, but it is part of a defense-in-depth posture that auditors expect to see alongside scoped key policies.
  • Cryptoperiod limits. NIST recommends bounding how long a single key is used. Automatic rotation enforces that bound without anyone needing to remember to do it.

The pragmatic argument is even simpler: enabling rotation costs almost nothing, requires zero code changes, and removes an audit finding permanently. There is rarely a good reason to leave it off on a symmetric CMK.

Warning: Each rotated version of a key counts toward a small additional KMS cost. AWS charges a per-key monthly fee plus a small charge for each rotation version retained. For the overwhelming majority of accounts this is a rounding error, but if you have tens of thousands of keys, model the cost before flipping it on everywhere.


How to fix it

Console

  1. Open the AWS KMS console and go to Customer managed keys.
  2. Select the key flagged by the check.
  3. Open the Key rotation tab.
  4. Check Automatically rotate this KMS key and, on supported keys, set your desired rotation period (between 90 and 2560 days).
  5. Save.

AWS CLI

Enable rotation on a single key:

aws kms enable-key-rotation --key-id 1234abcd-12ab-34cd-56ef-1234567890ab

If your account supports custom rotation periods, set one explicitly:

aws kms enable-key-rotation \
  --key-id 1234abcd-12ab-34cd-56ef-1234567890ab \
  --rotation-period-in-days 180

Confirm it took effect:

aws kms get-key-rotation-status --key-id 1234abcd-12ab-34cd-56ef-1234567890ab

To remediate at scale, loop over every customer-managed, symmetric, rotatable key in a region:

for key in $(aws kms list-keys --query 'Keys[].KeyId' --output text); do
  meta=$(aws kms describe-key --key-id "$key" \
    --query 'KeyMetadata.{Mgr:KeyManager,Spec:KeySpec,State:KeyState}' --output text)
  mgr=$(echo "$meta" | awk '{print $1}')
  spec=$(echo "$meta" | awk '{print $2}')
  state=$(echo "$meta" | awk '{print $3}')

  if [ "$mgr" = "CUSTOMER" ] && [ "$spec" = "SYMMETRIC_DEFAULT" ] && [ "$state" = "Enabled" ]; then
    echo "Enabling rotation on $key"
    aws kms enable-key-rotation --key-id "$key"
  fi
done

Tip: Run the loop with the enable-key-rotation line commented out first to print which keys would be changed. Review the list, then uncomment and run for real. A dry run on KMS is cheap insurance against touching a key you did not intend to.

Terraform

For any key you manage as code, the fix is a single argument:

resource "aws_kms_key" "app" {
  description             = "Application data encryption key"
  enable_key_rotation     = true
  rotation_period_in_days = 365
  deletion_window_in_days = 30
}

CloudFormation

{
  "Type": "AWS::KMS::Key",
  "Properties": {
    "Description": "Application data encryption key",
    "EnableKeyRotation": true,
    "KeyPolicy": { "...": "..." }
  }
}

Note: Enabling rotation does not re-encrypt your existing data, and it does not break decryption of older data. KMS keeps every previous version of the backing material around for as long as the key exists. Nothing you have already encrypted needs to be touched.


How to prevent it from happening again

Remediation fixes today's keys. Prevention stops the next manually created key from showing up with rotation off.

Catch it in CI/CD with policy-as-code

If teams provision KMS keys through Terraform, block merges that omit rotation. Here is a Checkov gate you can wire into a pull request pipeline:

checkov -d . --check CKV_AWS_7 --compact

CKV_AWS_7 fails any aws_kms_key resource without enable_key_rotation = true. For Open Policy Agent users, the equivalent Rego against a Terraform plan looks like this:

package kms.rotation

deny[msg] {
  resource := input.resource_changes[_]
  resource.type == "aws_kms_key"
  not resource.change.after.enable_key_rotation
  msg := sprintf("KMS key '%s' must have enable_key_rotation = true", [resource.address])
}

Enforce with AWS Config

The managed rule cmk-backing-key-rotation-enabled continuously evaluates every customer-managed key and marks any without rotation as non-compliant. Deploy it once and it watches the account for you:

aws configservice put-config-rule --config-rule '{
  "ConfigRuleName": "cmk-backing-key-rotation-enabled",
  "Source": {
    "Owner": "AWS",
    "SourceIdentifier": "CMK_BACKING_KEY_ROTATION_ENABLED"
  }
}'

Tip: Pair the AWS Config rule with an automatic remediation action that calls the AWS-EnableKMSKeyRotation SSM document. Non-compliant keys then get rotation switched on without a human in the loop, and you keep a clean audit trail in Systems Manager.


Best practices

  • Turn on rotation by default in your modules. Bake enable_key_rotation = true into your shared Terraform or CloudFormation modules so individual teams never have to remember it.
  • Pick a rotation period that matches your compliance needs. Annual rotation satisfies most frameworks. If you handle regulated data with stricter cryptoperiod requirements, drop the period to 90 to 180 days.
  • Tighten key policies, not just rotation. Rotation limits blast radius, but a wide-open kms:Decrypt grant undoes much of the benefit. Scope key policies and grants to the principals and services that actually need them.
  • Use separate keys per workload or data classification. Sharing one CMK across every service maximizes the blast radius. Per-application keys keep rotation and access boundaries meaningful.
  • Do not confuse rotation with re-encryption. If you need every object actually re-encrypted under fresh material, for example to retire an old key entirely, you have to re-encrypt the data yourself. Automatic rotation does not rewrite existing ciphertext.
  • Monitor key usage with CloudTrail. KMS logs every Decrypt and GenerateDataKey call. Alert on unusual spikes or access from unexpected principals to catch misuse early.

Enabling KMS key rotation is one of the cheapest security wins available in AWS. It is a single API call per key, it changes no application behavior, and it clears a recurring audit finding for good. Once your existing keys are remediated, push the setting into your IaC modules and a Config rule so it stays that way.