KMS Secrets Encrypted With Cmk Remediation
Triage and Remediation
- Remediation
Remediation
Using Console
Below are the step‑by‑step remediation instructions using the AWS Management Console so your AWS Secrets Manager secrets are encrypted with customer‑managed KMS keys (CMKs) instead of AWS‑managed keys.
1. Create (or Identify) a Customer‑Managed KMS Key
If you don’t already have a CMK for Secrets Manager:
-
Sign in to the AWS Management Console and go to AWS KMS
- Services → Key Management Service (KMS)
-
In the left pane, choose Customer managed keys.
-
Click Create key.
-
Under Key type, choose Symmetric and Encryption and decryption.
(This is standard for Secrets Manager.) -
Click Next.
-
Add an alias (e.g.,
alias/secrets-manager-key). -
Configure Key administrators (IAM users/roles that can manage the key), then Next.
-
Configure Key usage permissions:
- Add IAM roles/users used by your applications or services that access the secrets.
- Optionally add the Secrets Manager service principal if using resource policies (advanced).
-
Finish with Create key.
Keep the Key ID or Alias noted (e.g., alias/secrets-manager-key).
2. Update Each Secret to Use the CMK
For each secret currently using the default AWS‑managed key, change it to your CMK:
-
Go to AWS Secrets Manager in the console.
- Services → Secrets Manager
-
In Secrets, click the secret name you want to remediate.
-
On the secret’s details page, choose the Edit button.
-
Scroll down to the Encryption key or KMS key section.
-
From the dropdown, select your customer‑managed CMK
- e.g.,
alias/secrets-manager-key.
- e.g.,
-
Review other settings (no change needed for rotation unless desired).
-
Click Save.
Secrets Manager will re-encrypt the secret with the selected CMK.
3. Verify Permissions and Access
-
Still on the secret details page, use the Secret value → Retrieve secret value button.
- If retrieval succeeds for your application role/user, KMS permissions are correct.
-
If you get an access error:
- Go back to KMS → Customer managed keys.
- Select your key → Key policy.
- Ensure the application IAM roles/users are allowed
kms:Decryptandkms:GenerateDataKeyon this key.
4. (Optional) Enforce Use of CMKs Going Forward
To avoid regressions:
- In your infrastructure as code (CloudFormation/Terraform), always specify the
KmsKeyIdfor secrets. - In organizational policies (e.g., AWS Config rules, Security Hub controls), flag secrets using AWS‑managed keys instead of CMKs.
Repeat step 2 for all Secrets Manager secrets flagged by your scanner until each shows your customer‑managed KMS key as the encryption key.
Using CLI
Below are minimal, CLI-focused steps to ensure AWS Secrets Manager secrets are encrypted with a customer-managed KMS key (CMK), not the AWS-managed default key.
1. Identify Secrets Not Using a CMK
List all secrets and see which KMS key they use:
aws secretsmanager list-secrets \
--query 'SecretList[*].[Name,KmsKeyId]' \
--output table
Any secret with null or an AWS-managed key (like aws/secretsmanager) should be remediated.
2. (Optional) Create a Customer-Managed KMS Key (CMK)
If you don’t already have a CMK:
aws kms create-key \
--description "CMK for Secrets Manager encryption" \
--key-usage ENCRYPT_DECRYPT \
--origin AWS_KMS
Capture the KeyId from the output, e.g.:
"KeyId": "1234abcd-12ab-34cd-56ef-1234567890ab"
Optionally, add an alias:
aws kms create-alias \
--alias-name alias/secretsmanager-cmk \
--target-key-id 1234abcd-12ab-34cd-56ef-1234567890ab
You can use either the KeyId, full ARN, or alias ARN (e.g. arn:aws:kms:region:account-id:alias/secretsmanager-cmk) in the next step.
3. Update Each Secret to Use the CMK
For a single secret:
aws secretsmanager update-secret \
--secret-id MySecretNameOrArn \
--kms-key-id arn:aws:kms:REGION:ACCOUNT_ID:alias/secretsmanager-cmk
Or with a direct KeyId:
aws secretsmanager update-secret \
--secret-id MySecretNameOrArn \
--kms-key-id 1234abcd-12ab-34cd-56ef-1234567890ab
4. Bulk Remediation (All Secrets Without CMK)
Example Bash loop to switch all secrets with no KmsKeyId to a specific CMK alias:
KMS_KEY_ARN="arn:aws:kms:REGION:ACCOUNT_ID:alias/secretsmanager-cmk"
for secret in $(aws secretsmanager list-secrets \
--query "SecretList[?KmsKeyId==null].ARN" \
--output text); do
echo "Updating $secret"
aws secretsmanager update-secret \
--secret-id "$secret" \
--kms-key-id "$KMS_KEY_ARN"
done
5. Verify the Change
Re-check the KMS key for your secrets:
aws secretsmanager list-secrets \
--query 'SecretList[*].[Name,KmsKeyId]' \
--output table
Each remediated secret should now show your CMK ARN (or alias ARN) instead of null or an AWS-managed key.
Using Python
Below is a concise, step‑by‑step way to ensure AWS Secrets Manager secrets are encrypted with a customer‑managed KMS key (CMK) using Python (boto3).
1. Prerequisites
- Python 3.x
boto3installed:pip install boto3- IAM permissions:
kms:CreateKey,kms:DescribeKey,kms:ListKeys,kms:EnableKeyRotation(if creating/using CMK)secretsmanager:DescribeSecret,secretsmanager:UpdateSecret,secretsmanager:ListSecrets
2. Create (or Identify) a Customer-Managed KMS Key
If you already have a CMK you want to use, note its KeyId or ARN and skip to step 3.
2.1 Create a CMK with Python
import boto3
kms = boto3.client('kms', region_name='us-east-1') # adjust region
response = kms.create_key(
Description='CMK for Secrets Manager encryption',
KeyUsage='ENCRYPT_DECRYPT',
Origin='AWS_KMS'
)
cmk_id = response['KeyMetadata']['KeyId']
print("Created CMK:", cmk_id)
# (optional) Enable automatic key rotation
kms.enable_key_rotation(KeyId=cmk_id)
Record cmk_id or the full ARN (you can use either as KmsKeyId).
3. Check Existing Secrets for Default AWS-Managed KMS Key
import boto3
secretsmanager = boto3.client('secretsmanager', region_name='us-east-1')
paginator = secretsmanager.get_paginator('list_secrets')
for page in paginator.paginate():
for secret in page['SecretList']:
name = secret['Name']
kms_key_id = secret.get('KmsKeyId')
print(f"Secret: {name}, KmsKeyId: {kms_key_id}")
- If
KmsKeyIdisNone, the secret is using the default AWS-managed key. - If it’s set but not your CMK, you’ll want to change it.
4. Re-encrypt an Existing Secret with Your CMK
This changes the KMS key used going forward for all secret versions.
import boto3
region = 'us-east-1'
cmk_id = 'YOUR_CMK_ID_OR_ARN' # from step 2
secret_name = 'YOUR_SECRET_NAME'
secretsmanager = boto3.client('secretsmanager', region_name=region)
# (Optional) verify current key
desc = secretsmanager.describe_secret(SecretId=secret_name)
print("Current KmsKeyId:", desc.get('KmsKeyId'))
# Update secret to use CMK
response = secretsmanager.update_secret(
SecretId=secret_name,
KmsKeyId=cmk_id
)
print("Updated Secret VersionId:", response['VersionId'])
Notes:
update_secretwill cause future encrypt/decrypt operations to use this CMK.- Old ciphertext blobs are effectively re‑encrypted when accessed; you do not need to rewrite the secret value.
5. Create a New Secret Encrypted with CMK
import boto3
import json
secretsmanager = boto3.client('secretsmanager', region_name='us-east-1')
cmk_id = 'YOUR_CMK_ID_OR_ARN'
secret_name = 'my-app/db-credentials'
secret_value = {
"username": "dbuser",
"password": "dbpass"
}
response = secretsmanager.create_secret(
Name=secret_name,
KmsKeyId=cmk_id,
SecretString=json.dumps(secret_value)
)
print("Created secret:", response['ARN'])
6. Bulk Remediation: Migrate All Secrets to a CMK
Example: update every secret currently using the default AWS‑managed key.
import boto3
region = 'us-east-1'
cmk_id = 'YOUR_CMK_ID_OR_ARN'
secretsmanager = boto3.client('secretsmanager', region_name=region)
paginator = secretsmanager.get_paginator('list_secrets')
for page in paginator.paginate():
for secret in page['SecretList']:
secret_id = secret['ARN']
name = secret['Name']
kms_key_id = secret.get('KmsKeyId')
# If no KmsKeyId, it's using AWS-managed default
if kms_key_id is None:
print(f"Updating secret {name} to use CMK {cmk_id}")
secretsmanager.update_secret(
SecretId=secret_id,
KmsKeyId=cmk_id
)
7. KMS Key Policy Considerations
Ensure your CMK key policy allows Secrets Manager and principals that use the secret to use the key:
Minimal example snippet (KMS key policy statement):
{
"Sid": "AllowSecretsManagerUseOfTheKey",
"Effect": "Allow",
"Principal": { "Service": "secretsmanager.amazonaws.com" },
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:GenerateDataKey",
"kms:DescribeKey"
],
"Resource": "*"
}
(Also grant your IAM roles/users as needed.)
If you tell me how you currently organize your secrets (per app, per environment, etc.), I can adapt the bulk‑remediation script to your naming scheme or tagging strategy.
Using Terraform
# Customer-managed KMS key for encrypting Secrets Manager secrets
resource "aws_kms_key" "secrets_cmk" {
description = "CMK for encrypting Secrets Manager secrets"
enable_key_rotation = true
deletion_window_in_days = 30
# Optional: restrict key usage to Secrets Manager in this account
policy = data.aws_iam_policy_document.secrets_kms_policy.json
}
data "aws_iam_policy_document" "secrets_kms_policy" {
statement {
sid = "AllowAccountUseOfKey"
effect = "Allow"
actions = [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
]
principals {
type = "AWS"
identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"]
}
resources = ["*"]
}
statement {
sid = "AllowSecretsManagerToUseKey"
effect = "Allow"
actions = [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
]
principals {
type = "Service"
identifiers = ["secretsmanager.amazonaws.com"]
}
resources = ["*"]
}
}
data "aws_caller_identity" "current" {}
# Secrets Manager secret encrypted with the CMK above
resource "aws_secretsmanager_secret" "example" {
name = "SECRET_NAME" # replace with your secret name
description = "DESCRIPTION_OF_SECRET"
# Use the customer-managed KMS key instead of the AWS managed default
kms_key_id = aws_kms_key.secrets_cmk.arn
}
# (Optional) secret value
resource "aws_secretsmanager_secret_version" "example" {
secret_id = aws_secretsmanager_secret.example.id
secret_string = "SECRET_VALUE" # replace with your actual secret value or use sensitive input
}
Changing kms_key_id on an existing aws_secretsmanager_secret forces replacement of the secret resource in Terraform, which may cause a brief outage if consumers are not updated to the new ARN; plan carefully before applying.
Verification: terraform plan should show creation of aws_kms_key.secrets_cmk (if new) and either creation of a new aws_secretsmanager_secret.example or an update that replaces it, with kms_key_id set to the CMK ARN instead of the default AWS-managed key.