Back to blog
AWSBest PracticesCloud SecurityStorage

EBS Volume Not Using CMK: Move Off AWS-Managed Keys

Your EBS volume is encrypted but uses the AWS-managed key, not a CMK. Learn the risk, how to re-encrypt volumes with a customer-managed KMS key, and how to enforce it.

TL;DR

This check flags EBS volumes encrypted with the default AWS-managed KMS key (aws/ebs) instead of a customer-managed key (CMK). Switching to a CMK gives you control over key rotation, access policies, and audit visibility. Fix it by creating a CMK, setting it as the EBS encryption default, and re-encrypting existing volumes via snapshot copy.

Encrypting EBS volumes is table stakes, and most teams get that part right. What gets overlooked is which key does the encrypting. When you encrypt a volume without specifying a key, AWS falls back to the account-level default: the AWS-managed key aws/ebs. It works, the data is encrypted at rest, and the check for "is this volume encrypted" passes. But you have handed all key governance back to AWS, which is exactly what this check is here to catch.

The ebs_nocmk check identifies EBS volumes that are encrypted but rely on an AWS-managed key rather than a customer-managed KMS key (CMK). It is a maturity signal more than an emergency, but in regulated environments it is often a hard requirement.


What this check detects

Every encrypted EBS volume has a KmsKeyId attribute that points to the key used to encrypt it. This check inspects that key and determines whether it is:

  • An AWS-managed key — the aws/ebs alias, created and fully controlled by AWS (flagged)
  • A customer-managed key (CMK) — a key you created in KMS and control (passes)

You can see the difference yourself. List your volumes and inspect the key:

aws ec2 describe-volumes \
  --query 'Volumes[?Encrypted==`true`].[VolumeId,KmsKeyId]' \
  --output table

Then resolve the key to check who owns it:

aws kms describe-key \
  --key-id arn:aws:kms:us-east-1:111122223333:key/abcd-1234 \
  --query 'KeyMetadata.{KeyManager:KeyManager,Arn:Arn}'

If KeyManager returns AWS, the volume is using the managed key and this check fires. A CMK returns CUSTOMER.

Note: The aws/ebs key is real KMS encryption with envelope encryption and per-volume data keys. It is not weak crypto. The issue is governance and control, not the cipher.


Why it matters

The cryptography is the same either way. What changes is everything around the key, and that "everything" is what auditors, incident responders, and compliance frameworks actually care about.

You cannot control the key policy

AWS-managed keys come with a fixed key policy that you cannot edit. You cannot restrict which principals are allowed to decrypt data, you cannot add condition keys, and you cannot deny access to specific roles. With a CMK, the key policy becomes a second line of defense. Even if someone gains IAM permissions to attach a volume or restore a snapshot, they still need explicit kms:Decrypt grants on your CMK. That separation of duties is impossible with the managed key.

No control over rotation

AWS-managed keys rotate automatically every year, and you have no say in the schedule or the ability to force rotation after a suspected compromise. CMKs let you enable rotation on your own terms, rotate on demand, or disable a key entirely to instantly cut off access to data encrypted with it.

Weaker audit trail and no blast-radius control

Because the aws/ebs key is shared across many services and resources in your account, CloudTrail events tied to it are noisier and harder to attribute. A dedicated CMK per workload or environment gives you clean, scoped audit logs and lets you reason about exactly what one key protects.

Warning: You cannot share or copy a snapshot encrypted with an AWS-managed key to another account. Cross-account snapshot sharing requires a CMK. Teams often discover this only when they try to set up disaster recovery or migrate to a new account.

Compliance requirements

Several frameworks effectively mandate customer-managed keys for sensitive data, because the requirement is to demonstrate control over the key lifecycle. PCI DSS, HIPAA-aligned controls, and many internal security baselines call for documented key management that an AWS-managed key cannot satisfy.


How to fix it

There are two parts to remediation: set a CMK as your account default so new volumes are correct, and re-encrypt existing volumes that are using the managed key. Existing volumes cannot have their key changed in place, so you re-encrypt by copying a snapshot with the new key.

Step 1: Create a customer-managed key

aws kms create-key \
  --description "CMK for EBS volume encryption - prod" \
  --tags TagKey=Environment,TagValue=prod \
  --query 'KeyMetadata.KeyId' \
  --output text

Give it a friendly alias so it is easy to reference:

aws kms create-alias \
  --alias-name alias/ebs-prod \
  --target-key-id <key-id-from-above>

Enable automatic annual rotation:

aws kms enable-key-rotation --key-id <key-id>

Step 2: Set the CMK as the EBS default for the region

This makes every new volume in the region use your CMK unless explicitly told otherwise. Set it per region.

# Ensure encryption-by-default is on
aws ec2 enable-ebs-encryption-by-default

# Point the default at your CMK
aws ec2 modify-ebs-default-kms-key-id \
  --kms-key-id alias/ebs-prod

Confirm it stuck:

aws ec2 get-ebs-default-kms-key-id

Step 3: Re-encrypt existing volumes

You cannot rotate the key of an existing volume. The path is snapshot, copy with the CMK, create a new volume, swap it onto the instance.

Danger: Swapping a root or data volume requires stopping the instance and detaching the old volume. This is a downtime event. Test the full flow in a non-production environment, and confirm your new volume mounts correctly before deleting the original.

1. Snapshot the current volume:

aws ec2 create-snapshot \
  --volume-id vol-0abc123 \
  --description "pre-CMK migration" \
  --query 'SnapshotId' --output text

2. Copy the snapshot, re-encrypting with the CMK:

aws ec2 copy-snapshot \
  --source-region us-east-1 \
  --source-snapshot-id snap-0source123 \
  --encrypted \
  --kms-key-id alias/ebs-prod \
  --description "CMK-encrypted copy" \
  --query 'SnapshotId' --output text

3. Create a new volume from the CMK-encrypted snapshot:

aws ec2 create-volume \
  --availability-zone us-east-1a \
  --snapshot-id snap-0cmkcopy456 \
  --volume-type gp3 \
  --query 'VolumeId' --output text

4. Stop the instance, detach the old volume, attach the new one at the same device name:

aws ec2 stop-instances --instance-ids i-0instance789
aws ec2 wait instance-stopped --instance-ids i-0instance789

aws ec2 detach-volume --volume-id vol-0abc123
aws ec2 wait volume-available --volume-id vol-0abc123

aws ec2 attach-volume \
  --volume-id vol-0newcmk000 \
  --instance-id i-0instance789 \
  --device /dev/xvda

aws ec2 start-instances --instance-ids i-0instance789

Once you have verified the instance boots and the data is intact, you can delete the old volume and the interim snapshots.

Tip: For fleets, do not click through this by hand. Use AWS Backup or a Systems Manager Automation runbook to copy snapshots with the CMK at scale, and schedule the volume swaps during maintenance windows.


How to prevent it from happening again

Setting the regional default is the single highest-leverage fix, but defaults can be overridden and new regions start fresh. Back it up with policy and IaC.

Enforce the right key in Terraform

Make the CMK an explicit, non-optional argument in your modules so no one accidentally falls back to the managed key:

resource "aws_ebs_volume" "data" {
  availability_zone = "us-east-1a"
  size              = 100
  type              = "gp3"
  encrypted         = true
  kms_key_id        = aws_kms_key.ebs.arn

  tags = {
    Environment = "prod"
  }
}

resource "aws_ebs_encryption_by_default" "this" {
  enabled = true
}

resource "aws_ebs_default_kms_key" "this" {
  key_arn = aws_kms_key.ebs.arn
}

Block bad configs in CI with policy-as-code

A Checkov or OPA/Conftest gate in your pipeline catches volumes that omit a CMK before they reach AWS. A simple Rego rule:

package terraform.ebs

deny[msg] {
  resource := input.resource.aws_ebs_volume[name]
  not resource.kms_key_id
  msg := sprintf("EBS volume '%s' must specify a customer-managed kms_key_id", [name])
}

Catch drift with an SCP

For a hard organizational guardrail, a Service Control Policy can deny volume creation unless a CMK is supplied. Use this carefully and test it, since overly broad SCPs can break legitimate automation.

Warning: An SCP that denies ec2:CreateVolume without a key condition can also block AWS services that provision volumes on your behalf, including Auto Scaling and some managed services. Scope it to specific accounts and validate against your full launch path before enforcing.


Best practices

  • One CMK per environment or workload, not one per account. Separate keys for prod, staging, and dev keep your blast radius small and your audit logs clean without creating thousands of keys to manage.
  • Enable rotation on every CMK. Annual rotation is one API call and costs nothing extra. There is no reason to skip it.
  • Write tight key policies. Grant kms:Decrypt only to the roles that genuinely need it. The key policy is your enforcement layer, so treat it like one.
  • Turn on encryption-by-default in every region you use, not just the active ones. Unused regions are where shadow resources appear with the wrong defaults.
  • Watch the cost. CMKs carry a small monthly charge per key plus API request costs. This is negligible for most accounts, but if you create per-volume keys at scale, the request volume can add up.
  • Audit continuously. Defaults drift, regions get added, and someone always overrides a setting "just for testing." Keep this check running on a schedule rather than treating it as a one-time cleanup.

Moving from AWS-managed keys to CMKs is one of those changes that feels like paperwork until the day you need cross-account DR, or an auditor asks you to prove you can revoke access to a specific dataset. The work is modest, the ongoing cost is small, and the control you gain is real.