Existence of specific AWS KMS CMKs
More Info:
Ensure that a specific list of AWS KMS Customer Master Keys (CMKs) are available for use in your AWS account in order to meet strict security and compliance requirements in your organization.
Risk Level
Low
Address
Security
Compliance Standards
NIST
Remediation
How to ensure specific customer managed keys are used.
Using AWS Console
- Open the AWS Management Console and navigate to the service where you want to enforce the use of specific CMKs. Examples include Amazon S3, Amazon EBS, or AWS Lambda.
- Identify the specific CMK(s) that you want to enforce for encryption. These CMKs could be existing keys or ones that you need to create. (In the Cloudanix Console, navigate to "Misconfig" page and look for Affected Assets for "Existence of specific AWS KMS CMKs" Policy.)
- Follow the steps specific to the service you are working with:
a. Amazon S3:
- Open the S3 console and navigate to the bucket for which you want to enforce CMK usage.
- Click on the "Properties" tab.
- Scroll down to the "Default encryption" section.
- Enable default encryption and select "AWS Key Management Service (AWS KMS)" as the encryption type.
- Choose the desired CMK(s) from the drop-down list.
- Click "Save" to apply the changes. b. Amazon EBS:
- Open the EC2 console and navigate to the "EBS Volumes" page.
- Select the EBS volume for which you want to enforce CMK usage.
- From the "Actions" menu, choose "Modify Volume".
- In the "Modify Volume" dialog box, select the desired CMK from the "Encryption" section.
- Click "Modify" to apply the changes. c. AWS Lambda:
- Open the Lambda console and navigate to the function for which you want to enforce CMK usage.
- Click on the "Configuration" tab.
- Scroll down to the "Encryption configuration" section.
- Enable encryption in transit and select "Use AWS Key Management Service (AWS KMS) key" as the encryption key type.
- Choose the desired CMK from the drop-down list.
- Click "Save" to apply the changes.
- Repeat the steps for each service or resource where you want to enforce the use of specific CMKs.
Triage and Remediation
- Remediation
Remediation
Using Console
Below are step‑by‑step console instructions to find and safely remove/disallow specific AWS KMS CMKs.
1. Identify the specific CMKs
- Sign in to the AWS Management Console.
- Go to Key Management Service (KMS):
- In the search bar, type KMS and select Key Management Service.
- In the left navigation, choose Customer managed keys.
- Use filters/search to locate the specific CMKs by:
- Key ID, Key ARN, or
- Alias (e.g.,
alias/old-key,alias/disallowed-key).
Record:
- Key ID / ARN
- Region
- Alias
- Key type (symmetric/asymmetric, single‑Region/multi‑Region)
2. Check what uses the key (to avoid breaking workloads)
For each CMK you plan to remove:
- In KMS, click the key ID to open the key details.
- Review:
- Key policy – see which IAM principals can use it.
- Key rotation and tags – may hint at usage/owner.
- Check Key usage tab (if available) or use AWS services consoles to see dependencies:
- EBS: EC2 → Volumes → check Encryption column and KMS key field.
- RDS / Aurora: RDS → DB instances → each instance’s Configuration → KMS key.
- S3: S3 → Bucket → Properties → Default encryption → KMS key.
- CloudTrail: CloudTrail → Trails → Storage → KMS key.
- CloudWatch Logs, EFS, EKS, Lambda env vars, Secrets Manager, SSM Parameter Store: open each resource and confirm which KMS key is configured.
- Make a list of all resources still using this key.
Do not delete/disable the CMK until all critical resources are migrated to an allowed key.
3. Create or select an allowed replacement CMK (if needed)
If your policy requires different or restricted CMKs:
- In KMS console, under Customer managed keys, choose Create key.
- Choose:
- Key type: symmetric (most common) or asymmetric as needed.
- Key usage: e.g., Encrypt and decrypt.
- Configure:
- Key administrators (who can manage the key).
- Key users (who can use it to encrypt/decrypt).
- Any key policy requirements from your security standard.
- Add a clear alias (e.g.,
alias/standard-data-key). - Complete creation.
Repeat if multiple distinct CMKs are required.
4. Migrate services off the disallowed CMK
For each service that uses the disallowed CMK, update it to use the new/approved key:
Example patterns (AWS console)
-
EBS volumes (new):
EC2 → Launch instance → Advanced details → Encryption → select new KMS key. -
EBS volumes (existing; snapshot‑based):
- Create a snapshot of the encrypted volume.
- Copy the snapshot and choose Encrypt with the new CMK.
- Create a new volume from the copied snapshot.
- Attach the new volume and migrate data (or use AMI based approach for root volumes).
-
RDS:
- You cannot change KMS key on an existing encrypted DB directly.
Typical approach:- Take a snapshot of the DB.
- Copy the snapshot and choose the new CMK for encryption.
- Restore a new DB instance from the copied snapshot.
- Cut over your application to the new DB.
- You cannot change KMS key on an existing encrypted DB directly.
-
S3 default bucket encryption:
- S3 → select bucket → Properties.
- Under Default encryption, click Edit.
- Choose AWS KMS key and select the new CMK.
- For existing objects, use S3 Batch Operations or lifecycle/automation to re‑encrypt if required by policy.
-
CloudTrail:
- CloudTrail → Trails → select trail → Edit.
- Under Log file SSE-KMS encryption, select the new KMS key.
- Save changes.
-
CloudWatch Logs:
- CloudWatch → Log groups → select log group.
- Actions → Edit (or Edit encryption).
- Select the new KMS key.
-
Secrets Manager:
- Secrets Manager → select secret.
- Edit → choose Encryption key → select new CMK → save.
-
SSM Parameter Store (SecureString):
- For each parameter: Edit the parameter and choose the new CMK. (Some may require re‑creation; check the console options.)
Repeat for all services that referenced the disallowed key.
5. Disable key usage (soft stop) for the disallowed CMKs
Once you are sure no active workloads need the CMK:
- KMS → Customer managed keys → select the specific CMK.
- On the key details page, click Disable.
- Confirm Disable.
Effects:
- New encrypt/decrypt operations will fail with this key.
- Existing encrypted data remains encrypted; you can still re‑enable the key if you discover a missed dependency.
Keep the key disabled for a safety period your organization approves (e.g., 7–30 days) and monitor for failures in CloudWatch/CloudTrail.
6. Schedule CMK deletion (hard removal)
When fully confident the key is no longer needed:
- In KMS → Customer managed keys, select the CMK.
- On the key details page, choose Schedule key deletion.
- Choose a waiting period (7–30 days; choose the maximum allowed if you want a safer rollback window).
- Confirm.
During the waiting period, you can Cancel deletion from the same key page if needed.
After the waiting period:
- The key material and metadata are permanently deleted.
- Any data still encrypted under this key becomes unrecoverable.
7. Prevent future creation/use of disallowed CMKs
To keep the environment compliant:
- Use IAM policies and/or Service Control Policies (SCPs) (if using AWS Organizations) to:
- Deny creation of CMKs that don’t adhere to your standards (based on tags, aliases, or regions).
- Deny use of specific key ARNs (the ones you just removed or disallowed patterns).
- Optionally:
- Centralize key creation and management to a limited admin group.
- Enforce tagging or alias conventions for approved keys.
If you share the exact policy requirement (e.g., “no CMKs in account X”, or “no CMKs with alias starting with X”), I can tailor the console steps and example IAM/SCP snippets to that specific control.
Using CLI
Below are step‑by‑step AWS CLI–based instructions to remediate a finding that flags the existence of specific AWS KMS customer managed keys (CMKs) (for example: legacy, unused, non‑compliant, or shadow keys).
I’ll assume the goal is to identify those CMKs and securely decommission them (disable → schedule deletion), while avoiding breaking workloads.
1. Identify the Specific CMKs
If you already have the Key IDs / ARNs from the finding, you can skip to step 3. Otherwise, list and filter.
# List all customer managed keys in the account
aws kms list-keys --query 'Keys[].KeyId' --output text
For each key, get details and tags (to identify the “specific” ones):
KEY_ID=<your-key-id>
aws kms describe-key --key-id "$KEY_ID"
aws kms list-resource-tags --key-id "$KEY_ID"
Common filters you might apply:
- Key alias (e.g.,
alias/legacy-*,alias/test-*) - Tags (e.g.,
Environment=Dev,Owner=DeprecatedApp) - Creation date (
CreationDateindescribe-keyoutput) - Key state (
Enabled,Disabled, etc.)
You can get aliases to match keys more easily:
aws kms list-aliases
2. Confirm No Active Dependencies
Before disabling or deleting a key, verify nothing critical uses it.
2.1. Check CloudTrail for usage (recent period)
# Example: last 7 days, region-specific, adjust time as needed
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=ResourceName,AttributeValue=$KEY_ID \
--max-results 50
Or search for the key ARN instead of KEY_ID if you have it.
If you see recent Encrypt, Decrypt, GenerateDataKey, etc., you must first migrate dependent workloads to another key (e.g., update services to use a new CMK).
3. Disable the Specific CMKs (Safe First Step)
Disabling is reversible and is safer than immediate deletion.
# Disable the key
aws kms disable-key --key-id "$KEY_ID"
Verify:
aws kms describe-key --key-id "$KEY_ID" \
--query 'KeyMetadata.KeyState' --output text
# Should return: Disabled
If something breaks after disabling, you can re‑enable:
aws kms enable-key --key-id "$KEY_ID"
4. Schedule Deletion (Permanent Remediation)
Once you’ve confirmed the CMK is not needed:
# Schedule deletion with a waiting period (7–30 days)
aws kms schedule-key-deletion \
--key-id "$KEY_ID" \
--pending-window-in-days 30
Verify:
aws kms describe-key --key-id "$KEY_ID" \
--query 'KeyMetadata.[KeyState,DeletionDate]' --output text
# Should show: PendingDeletion <date>
If you scheduled deletion by mistake and need to cancel it:
aws kms cancel-key-deletion --key-id "$KEY_ID"
5. Remove or Update Aliases Pointing to These CMKs
If the finding is related to aliases pointing to non‑compliant keys, repoint or delete aliases.
5.1. Repoint alias to a compliant CMK
ALIAS_NAME="alias/your-alias"
NEW_KEY_ID="<new-compliant-key-id>"
aws kms update-alias \
--alias-name "$ALIAS_NAME" \
--target-key-id "$NEW_KEY_ID"
5.2. Delete alias if not needed
ALIAS_NAME="alias/old-key"
aws kms delete-alias --alias-name "$ALIAS_NAME"
6. (Optional) Enforce Future Compliance
If the finding is about certain “types” of CMKs existing (e.g., keys without rotation, with bad policies):
- Enable rotation on compliant keys:
aws kms enable-key-rotation --key-id "$KEY_ID"
- Restrict who can create CMKs via IAM policies.
- Use tags and config rules / Security Hub controls to detect non‑compliant CMKs early.
If you share one example Key ARN or the exact rule text (e.g., from Security Hub or a CSPM), I can give you precise CLI commands tailored to that specific misconfiguration.
Using Python
Below is a concise, step‑by‑step way to remediate disallowed / misconfigured AWS KMS CMKs using Python (boto3). Adjust to your policy (e.g., delete specific CMKs, disable them, or remove aliases).
1. Prerequisites
pip install boto3
Configure AWS credentials with permissions for KMS (e.g., kms:ListKeys, kms:DescribeKey, kms:DisableKey, kms:ScheduleKeyDeletion, kms:DeleteAlias, etc.).
2. Identify the CMKs to Remediate
You need a rule to detect “bad” CMKs, for example:
- Keys with a specific alias name/pattern (e.g.,
alias/bad-key-*) - Keys in a certain account/region that must not exist
- Keys with specific tags or key policies
2.1. List all CMKs and filter by criteria
import boto3
kms = boto3.client('kms', region_name='us-east-1')
def list_all_keys():
keys = []
paginator = kms.get_paginator('list_keys')
for page in paginator.paginate():
keys.extend(page['Keys'])
return keys
def find_disallowed_keys(alias_prefix="alias/bad-key-"):
disallowed_key_ids = []
# 1) Map aliases to key IDs
alias_paginator = kms.get_paginator('list_aliases')
alias_map = {} # key_id -> [aliases]
for page in alias_paginator.paginate():
for alias in page['Aliases']:
key_id = alias.get('TargetKeyId')
if key_id:
alias_map.setdefault(key_id, []).append(alias['AliasName'])
# 2) Filter keys by alias prefix (or other conditions)
for key in list_all_keys():
key_id = key['KeyId']
aliases = alias_map.get(key_id, [])
if any(a.startswith(alias_prefix) for a in aliases):
disallowed_key_ids.append(key_id)
return disallowed_key_ids
bad_keys = find_disallowed_keys()
print("Disallowed CMKs:", bad_keys)
Replace alias_prefix or add your own detection logic.
3. Disable the CMKs (Immediate Risk Reduction)
Disabling stops cryptographic operations but preserves the key for investigation.
def disable_keys(key_ids):
for key_id in key_ids:
print(f"Disabling key: {key_id}")
kms.disable_key(KeyId=key_id)
disable_keys(bad_keys)
4. (Optional) Remove Disallowed Aliases
If your policy requires removing specific aliases instead of (or prior to) deleting keys:
def delete_aliases_for_keys(key_ids):
key_ids_set = set(key_ids)
paginator = kms.get_paginator('list_aliases')
for page in paginator.paginate():
for alias in page['Aliases']:
key_id = alias.get('TargetKeyId')
alias_name = alias['AliasName']
if key_id in key_ids_set:
print(f"Deleting alias {alias_name} for key {key_id}")
kms.delete_alias(AliasName=alias_name)
delete_aliases_for_keys(bad_keys)
5. Schedule Deletion of the CMKs (Permanent Remediation)
Warning: After the waiting period, key material is permanently deleted and any data encrypted under these CMKs that doesn’t have a re‑encrypted copy becomes unrecoverable.
def schedule_key_deletion(key_ids, waiting_period_days=30):
for key_id in key_ids:
print(f"Scheduling deletion for key: {key_id}")
kms.schedule_key_deletion(
KeyId=key_id,
PendingWindowInDays=waiting_period_days # 7–30
)
schedule_key_deletion(bad_keys, waiting_period_days=30)
6. (Optional) Enforce “Good” CMK Configuration Instead
If the misconfiguration is about how CMKs are configured (not just their existence), you may:
-
Ensure rotation is enabled:
def enable_rotation(key_ids):for key_id in key_ids:print(f"Enabling rotation for key: {key_id}")kms.enable_key_rotation(KeyId=key_id) -
Fix key policies or tags via
put_key_policyandtag_resource.
7. End‑to‑End Script Skeleton
import boto3
kms = boto3.client('kms', region_name='us-east-1')
def remediate_disallowed_kms_keys(alias_prefix="alias/bad-key-", delete_after_days=30):
# 1) Find disallowed CMKs
bad_keys = find_disallowed_keys(alias_prefix)
if not bad_keys:
print("No disallowed CMKs found.")
return
# 2) Disable them
disable_keys(bad_keys)
# 3) Remove aliases
delete_aliases_for_keys(bad_keys)
# 4) Schedule deletion
schedule_key_deletion(bad_keys, waiting_period_days=delete_after_days)
print("Remediation complete for keys:", bad_keys)
# Reuse helper functions defined above: list_all_keys, find_disallowed_keys,
# disable_keys, delete_aliases_for_keys, schedule_key_deletion.
if __name__ == "__main__":
remediate_disallowed_kms_keys(alias_prefix="alias/bad-key-", delete_after_days=30)
If you share your exact policy (e.g., “any CMK not tagged Environment=Prod must be deleted”), I can adapt the detection and remediation logic precisely to that.
Using Terraform
resource "aws_kms_key" "SPECIFIC_KMS_CMK" {
description = "CMK for SPECIFIC_PURPOSE (e.g., S3 bucket encryption, RDS, etc.)"
key_usage = "ENCRYPT_DECRYPT"
customer_master_key_spec = "SYMMETRIC_DEFAULT"
# Adjust as needed
deletion_window_in_days = 30
enable_key_rotation = true
tags = {
Name = "SPECIFIC_KMS_CMK"
Environment = "YOUR_ENVIRONMENT"
Owner = "YOUR_TEAM"
}
}
resource "aws_kms_alias" "SPECIFIC_KMS_CMK_ALIAS" {
name = "alias/YOUR_EXPECTED_ALIAS_NAME" # e.g., alias/app-data-key
target_key_id = aws_kms_key.SPECIFIC_KMS_CMK.key_id
}
Substitute:
SPECIFIC_KMS_CMK/SPECIFIC_KMS_CMK_ALIASwith your Terraform resource names.SPECIFIC_PURPOSE,YOUR_ENVIRONMENT,YOUR_TEAM, andalias/YOUR_EXPECTED_ALIAS_NAMEwith your required values so that the expected CMKs and aliases “exist” as required by your control.
This creates the required CMKs; no existing key is replaced unless you change an immutable field (e.g., customer_master_key_spec), which would force replacement and could cause outage for workloads using the old key.
Verification: terraform plan should show + create for the aws_kms_key and aws_kms_alias resources corresponding to the keys that were previously missing.