Skip to main content

KMS Secrets Encrypted With Cmk Remediation

Triage and 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:

  1. Sign in to the AWS Management Console and go to AWS KMS

    • Services → Key Management Service (KMS)
  2. In the left pane, choose Customer managed keys.

  3. Click Create key.

  4. Under Key type, choose Symmetric and Encryption and decryption.
    (This is standard for Secrets Manager.)

  5. Click Next.

  6. Add an alias (e.g., alias/secrets-manager-key).

  7. Configure Key administrators (IAM users/roles that can manage the key), then Next.

  8. 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).
  9. 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:

  1. Go to AWS Secrets Manager in the console.

    • Services → Secrets Manager
  2. In Secrets, click the secret name you want to remediate.

  3. On the secret’s details page, choose the Edit button.

  4. Scroll down to the Encryption key or KMS key section.

  5. From the dropdown, select your customer‑managed CMK

    • e.g., alias/secrets-manager-key.
  6. Review other settings (no change needed for rotation unless desired).

  7. Click Save.

Secrets Manager will re-encrypt the secret with the selected CMK.


3. Verify Permissions and Access

  1. Still on the secret details page, use the Secret valueRetrieve secret value button.

    • If retrieval succeeds for your application role/user, KMS permissions are correct.
  2. 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:Decrypt and kms:GenerateDataKey on this key.

4. (Optional) Enforce Use of CMKs Going Forward

To avoid regressions:

  1. In your infrastructure as code (CloudFormation/Terraform), always specify the KmsKeyId for secrets.
  2. 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
  • boto3 installed:
    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 KmsKeyId is None, 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_secret will 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.