Skip to main content

AWS KMS Keys Should Not Be Deleted Unintentionally

Overview

This check identifies AWS KMS customer-managed keys (CMKs) that are scheduled for deletion. When a KMS key is scheduled for deletion, AWS enforces a mandatory waiting period (7-30 days) before permanently deleting the key. This check flags keys in the "Pending deletion" state so you can review and cancel accidental or unauthorized deletion requests.

Risk

Severity: Critical

Deleting a KMS key is an irreversible action with severe consequences:

  • Permanent data loss: Any data encrypted with the deleted key becomes permanently unrecoverable
  • Service disruptions: Applications relying on the key will fail to decrypt data
  • Backup restoration failures: Encrypted backups become unusable
  • Compliance violations: Loss of encrypted data may violate data retention requirements

Once deleted, there is no way to recover a KMS key or the data encrypted with it.

Remediation Steps

Prerequisites

You need AWS Console access or CLI credentials with the kms:CancelKeyDeletion and kms:EnableKey permissions.

AWS Console Method

  1. Sign in to the AWS KMS Console
  2. In the left navigation, click Customer managed keys
  3. Look for keys with status Pending deletion (shown in the Status column)
  4. Click on the key name to open its details
  5. Click the Key actions button
  6. Select Cancel key deletion
  7. Confirm the cancellation when prompted

The key status will change from "Pending deletion" to "Disabled". If you want to use the key again, you will need to enable it.

To re-enable the key after canceling deletion:

  1. On the key details page, click Key actions
  2. Select Enable
  3. The key status will change to "Enabled"
AWS CLI Method

List all KMS keys and find those pending deletion:

aws kms list-keys --region us-east-1 --query 'Keys[*].KeyId' --output text | \
xargs -I {} aws kms describe-key --key-id {} --region us-east-1 \
--query 'KeyMetadata.[KeyId, KeyState, DeletionDate]' --output text | \
grep PendingDeletion

Cancel deletion for a specific key:

aws kms cancel-key-deletion \
--key-id <your-key-id> \
--region us-east-1

Replace <your-key-id> with the actual Key ID or Key ARN (e.g., 1234abcd-12ab-34cd-56ef-1234567890ab).

Re-enable the key after canceling deletion:

aws kms enable-key \
--key-id <your-key-id> \
--region us-east-1
CloudFormation Prevention

CloudFormation does not support canceling key deletion, but you can prevent accidental deletion by:

  1. Using DeletionPolicy: Add DeletionPolicy: Retain to your KMS key resources
  2. Enabling key rotation: Rotate keys instead of deleting them
AWSTemplateFormatVersion: '2010-09-09'
Description: KMS Key with deletion protection

Resources:
MyKMSKey:
Type: AWS::KMS::Key
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Properties:
Description: Protected KMS key
EnableKeyRotation: true
KeyPolicy:
Version: '2012-10-17'
Statement:
- Sid: Enable IAM User Permissions
Effect: Allow
Principal:
AWS: !Sub 'arn:aws:iam::${AWS::AccountId}:root'
Action: 'kms:*'
Resource: '*'
- Sid: Restrict Key Deletion
Effect: Deny
Principal: '*'
Action:
- kms:ScheduleKeyDeletion
- kms:Delete*
Resource: '*'
Condition:
StringNotEquals:
'aws:PrincipalArn': !Sub 'arn:aws:iam::${AWS::AccountId}:role/KMSAdminRole'
Terraform Prevention

Terraform does not support canceling key deletion, but you can prevent accidental deletion:

resource "aws_kms_key" "protected_key" {
description = "Protected KMS key"
enable_key_rotation = true
deletion_window_in_days = 30 # Maximum waiting period

# Prevent Terraform from destroying the key
lifecycle {
prevent_destroy = true
}

policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "Enable IAM User Permissions"
Effect = "Allow"
Principal = {
AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"
}
Action = "kms:*"
Resource = "*"
},
{
Sid = "Restrict Key Deletion"
Effect = "Deny"
Principal = "*"
Action = [
"kms:ScheduleKeyDeletion",
"kms:Delete*"
]
Resource = "*"
Condition = {
StringNotEquals = {
"aws:PrincipalArn" = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/KMSAdminRole"
}
}
}
]
})

tags = {
Name = "protected-key"
Environment = "production"
}
}

resource "aws_kms_alias" "protected_key_alias" {
name = "alias/protected-key"
target_key_id = aws_kms_key.protected_key.key_id
}

data "aws_caller_identity" "current" {}

Verification

After canceling the deletion:

  1. Return to the Customer managed keys page in the KMS Console
  2. Confirm the key status has changed from "Pending deletion" to "Disabled"
  3. If you enabled the key, verify the status shows "Enabled"
CLI Verification
aws kms describe-key \
--key-id <your-key-id> \
--region us-east-1 \
--query 'KeyMetadata.{KeyId:KeyId, KeyState:KeyState, DeletionDate:DeletionDate}'

Expected output after canceling deletion:

{
"KeyId": "1234abcd-12ab-34cd-56ef-1234567890ab",
"KeyState": "Disabled",
"DeletionDate": null
}

Additional Resources

Notes

  • Waiting period: AWS enforces a 7-30 day waiting period before permanent deletion. Use this window to identify and cancel unintended deletions.
  • Disabled state: After canceling deletion, the key is in a "Disabled" state. You must explicitly enable it to use it again.
  • Consider disabling instead of deleting: If you no longer need a key, disable it rather than deleting it. Disabled keys can be re-enabled if needed later.
  • Audit deletion requests: Set up CloudTrail alerts for ScheduleKeyDeletion API calls to catch unauthorized deletion attempts early.
  • Separation of duties: Restrict the kms:ScheduleKeyDeletion permission to a limited set of administrators to prevent accidental or malicious deletion.