Your DocumentDB cluster is encrypted, but with an AWS-managed key you do not control. That means no custom key policies, no independent rotation, and no ability to revoke access during an incident. Recreate the cluster with a customer-managed KMS key to take back control.
Encryption at rest gets a lot of attention in compliance checklists, and rightly so. But there is a meaningful gap between "encrypted" and "encrypted with a key you actually govern." This check flags Amazon DocumentDB clusters that fall into the first bucket: encryption is on, but it is backed by an AWS-managed KMS key rather than a customer-managed key (CMK).
On the surface the data is protected the same way. The difference shows up when you need to do anything beyond "trust AWS to handle it": restrict who can use the key, audit exactly who decrypted what, rotate on your own schedule, or cut off access fast when something goes wrong.
What this check detects
The docdb_nocmk check inspects each DocumentDB cluster and looks at the KMS key tied to its storage encryption. DocumentDB clusters are always encrypted at rest when storage encryption is enabled, and the key used falls into one of two camps:
- AWS-managed key (
aws/rdsor the default service key): created and fully controlled by AWS. You cannot modify its policy, view its usage in fine-grained detail, or schedule its deletion. - Customer-managed key (CMK): a key you create in KMS, with a policy you write, rotation you configure, and full CloudTrail visibility into every
Encrypt,Decrypt, andGenerateDataKeycall.
The check passes when a cluster uses a CMK and fails when it uses the AWS-managed key. It does not flag clusters that have encryption disabled entirely, that is a separate, more severe finding.
Note: DocumentDB uses the same underlying encryption mechanics as Amazon RDS and Aurora. The KMS key is bound at cluster creation time and cannot be changed in place, which is why remediation requires a restore rather than a simple toggle.
Why it matters
With an AWS-managed key, AWS owns the key policy. You inherit a policy that grants the DocumentDB service access on your behalf, and you cannot tighten it. That removes several controls that matter during a real incident or audit.
You cannot revoke access independently
Imagine credentials for a role with DocumentDB access leak. With a CMK, you can remove that principal from the key policy or disable the key, and decryption stops cold, even if the IAM permissions are still messy and being cleaned up. With an AWS-managed key, you have no such lever. Your only options are IAM and cluster-level changes, which are slower and easier to miss.
No granular audit trail
CMK usage is logged in CloudTrail at the key level. You can see which principal requested a data key, when, and from where. AWS-managed key usage is far less visible, which makes incident reconstruction and access reviews harder.
Rotation on your terms
AWS-managed keys rotate automatically once a year, and you cannot change that. With a CMK you can enable annual automatic rotation, force a manual rotation after a suspected exposure, or align rotation with your compliance cadence.
Warning: Frameworks like SOC 2, HIPAA, PCI DSS, and many internal security baselines expect customer-managed keys for regulated data. An AWS-managed key often technically satisfies "encryption at rest" but fails the "key management and access control" requirements auditors actually probe.
Cross-account and key separation boundaries
CMKs let you build clean trust boundaries: a key in a central security account, granted to specific workload accounts, with usage that you alone can suspend. This is the backbone of a defense-in-depth key strategy, and it is simply not available with the AWS-managed key.
How to fix it
You cannot swap the KMS key on a running DocumentDB cluster. The supported path is to take a snapshot, copy the snapshot while re-encrypting it with your CMK, then restore a new cluster from that copy. Plan for a cutover window.
Danger: Restoring to a new cluster means a new endpoint. Your applications must be repointed to the new connection string, and the old cluster deleted only after you have verified the new one. Treat this as a planned migration, not a quick fix.
Step 1: Create a customer-managed key
aws kms create-key \
--description "CMK for DocumentDB cluster encryption" \
--tags TagKey=Purpose,TagValue=documentdb-encryption
# Note the KeyId from the output, then add a friendly alias
aws kms create-alias \
--alias-name alias/docdb-prod-cmk \
--target-key-id <key-id>
# Enable automatic annual rotation
aws kms enable-key-rotation --key-id <key-id>
Step 2: Snapshot the existing cluster
aws docdb create-db-cluster-snapshot \
--db-cluster-identifier my-docdb-cluster \
--db-cluster-snapshot-identifier my-docdb-snapshot-pre-cmk
Wait for the snapshot to reach available:
aws docdb describe-db-cluster-snapshots \
--db-cluster-snapshot-identifier my-docdb-snapshot-pre-cmk \
--query 'DBClusterSnapshots[0].Status'
Step 3: Copy the snapshot and re-encrypt with the CMK
aws docdb copy-db-cluster-snapshot \
--source-db-cluster-snapshot-identifier my-docdb-snapshot-pre-cmk \
--target-db-cluster-snapshot-identifier my-docdb-snapshot-cmk \
--kms-key-id alias/docdb-prod-cmk
Step 4: Restore a new cluster from the re-encrypted snapshot
aws docdb restore-db-cluster-from-snapshot \
--db-cluster-identifier my-docdb-cluster-cmk \
--snapshot-identifier my-docdb-snapshot-cmk \
--engine docdb \
--kms-key-id alias/docdb-prod-cmk \
--vpc-security-group-ids sg-0123456789abcdef0 \
--db-subnet-group-name my-docdb-subnet-group
Then add instances to the restored cluster, since the snapshot restore creates the cluster without instances:
aws docdb create-db-instance \
--db-instance-identifier my-docdb-cmk-instance-1 \
--db-cluster-identifier my-docdb-cluster-cmk \
--engine docdb \
--db-instance-class db.r6g.large
Step 5: Cut over and clean up
- Repoint your application to the new cluster endpoint.
- Validate reads, writes, and any read replicas behave as expected.
- Once confident, delete the old cluster and the intermediate snapshots.
Tip: If your DocumentDB cluster name is referenced by DNS or a service discovery layer rather than hardcoded, point that record at the new endpoint to make the cutover a one-line change you can roll back quickly.
Doing it right the first time with IaC
For new clusters, never leave the key unset. Specify the CMK explicitly. In Terraform:
resource "aws_kms_key" "docdb" {
description = "CMK for DocumentDB"
enable_key_rotation = true
deletion_window_in_days = 30
}
resource "aws_docdb_cluster" "main" {
cluster_identifier = "my-docdb-cluster"
engine = "docdb"
master_username = var.master_username
master_password = var.master_password
storage_encrypted = true
kms_key_id = aws_kms_key.docdb.arn
db_subnet_group_name = aws_docdb_subnet_group.main.name
vpc_security_group_ids = [aws_security_group.docdb.id]
}
In CloudFormation:
{
"Type": "AWS::DocDB::DBCluster",
"Properties": {
"DBClusterIdentifier": "my-docdb-cluster",
"StorageEncrypted": true,
"KmsKeyId": { "Ref": "DocDbCmk" },
"MasterUsername": { "Ref": "MasterUsername" },
"MasterUserPassword": { "Ref": "MasterPassword" }
}
}
How to prevent it from happening again
Remediating one cluster is fine. Stopping the next one from shipping without a CMK is what actually moves the needle.
Gate it in CI/CD with policy-as-code
Catch missing or AWS-managed keys before the cluster is created. A Checkov custom policy or OPA/Conftest rule against your Terraform plan works well. Example Conftest policy:
package main
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_docdb_cluster"
not resource.change.after.kms_key_id
msg := sprintf("DocumentDB cluster '%s' must specify a customer-managed kms_key_id", [resource.address])
}
Wire this into your pipeline so a plan without an explicit kms_key_id fails the build:
terraform plan -out=tfplan
terraform show -json tfplan > plan.json
conftest test plan.json --policy ./policies
Use an SCP to discourage default-key clusters
Service Control Policies cannot inspect which KMS key DocumentDB uses directly, but you can require that any KMS usage targets approved keys through condition keys on broader actions, and you can deny cluster creation without storage encryption. Pair this with detective controls below for real coverage.
Continuous detection
Run a recurring scan with Lensix so any cluster that drifts, or that someone spins up by hand in the console, surfaces the docdb_nocmk finding within a scan cycle rather than at audit time. Detective controls catch what preventive controls miss, and the two together are far stronger than either alone.
Tip: Standardize on a small set of named CMKs per environment (for example alias/docdb-prod-cmk) and reference the alias in your modules. Engineers get a paved road, and your scans get a clean, predictable signal.
Best practices
- Always set
kms_key_idexplicitly on DocumentDB clusters, even when you intend to use an account-default CMK. Explicit beats implicit, and it documents intent. - Enable automatic key rotation on the CMK and confirm it stays on.
- Write a tight key policy. Grant only the principals and the DocumentDB service the operations they need. Avoid
kms:*grants to broad principals. - Separate keys by environment and sensitivity. Do not share one CMK across prod and dev, since a shared key creates a shared blast radius.
- Monitor key usage in CloudTrail and alert on unexpected
DecryptorDisablecalls. - Set a deletion window on CMKs (7 to 30 days) so an accidental scheduled deletion can be cancelled before data becomes unrecoverable.
Danger: If a CMK used by a DocumentDB cluster is deleted or scheduled for deletion, the encrypted data becomes permanently inaccessible. Protect these keys with restrictive policies, and never grant kms:ScheduleKeyDeletion to roles that do not absolutely need it.
Moving from an AWS-managed key to a CMK is a one-time migration cost that buys you durable control: who can decrypt, when keys rotate, and how fast you can react when something goes wrong. For data sitting in a database, that control is worth the cutover.

