This check flags EFS file systems encrypted with the default AWS-managed KMS key instead of a customer-managed key (CMK). Without a CMK you lose control over key rotation, access policies, and cross-account boundaries. The fix is to create a new EFS file system encrypted with your own CMK and migrate the data, since encryption keys cannot be changed in place.
Amazon EFS encrypts data at rest by default, which is good. But "encrypted" and "you control the encryption" are two different things. When EFS uses the default aws/elasticfilesystem key, AWS owns the policy that governs that key. You can't tighten access, you can't audit usage the way you'd want, and you can't revoke access in an incident. This check catches file systems sitting on that default key so you can move them to a customer-managed key (CMK) that you actually control.
Note: The default AWS-managed key (often shown as aws/elasticfilesystem) is created automatically per region the first time you use EFS encryption. It's free, but the key policy is managed by AWS and you cannot edit it.
What this check detects
The efs_nocmk check inspects every EFS file system in your account and reports any whose KmsKeyId points to the AWS-managed default key rather than a customer-managed CMK. A file system passes when it is encrypted with a CMK that lives in your account (or a CMK shared from another account you trust).
You can see what key a file system uses with the CLI:
aws efs describe-file-systems \
--query 'FileSystems[].{ID:FileSystemId,Encrypted:Encrypted,Key:KmsKeyId}' \
--output table
If the Key value resolves to an alias of aws/elasticfilesystem, that file system is using the default key and will be flagged. To confirm an ARN maps to the AWS-managed key:
aws kms describe-key \
--key-id arn:aws:kms:us-east-1:111122223333:key/abcd-1234 \
--query 'KeyMetadata.{Manager:KeyManager,Alias:Description}'
A KeyManager value of AWS means it's the managed default. CUSTOMER means it's a CMK you own.
Why it matters
Encryption at rest only buys you something if the key access is controlled the way your security model expects. With the default key, several gaps open up.
You can't write a key policy
The default key's policy is AWS-managed and effectively grants any principal in the account with EFS permissions the ability to use it. You can't add a condition that restricts decryption to specific roles, VPCs, or source services. With a CMK, you control exactly which IAM principals can call kms:Decrypt against the data.
You can't revoke access during an incident
Imagine a compromised role with EFS mount permissions. With a CMK, you can disable the key or tighten its policy to cut off decryption immediately while you investigate. With the default key, that lever doesn't exist. You're stuck removing IAM permissions one by one and hoping you covered everything.
Cross-account sharing is limited
AWS-managed keys cannot be shared across accounts. If you ever need to grant another account access to encrypted EFS data, or you're consolidating under a multi-account org structure, the default key boxes you in. CMKs can be shared through key policies and grants.
Warning: Many compliance frameworks (PCI DSS, HIPAA, SOC 2, FedRAMP) expect customer-managed keys for sensitive data so that key lifecycle and access are auditable and under your control. Auditors frequently flag default-key usage even though the data is technically encrypted.
Rotation and audit visibility
CMKs let you configure automatic annual rotation and review every key usage event in CloudTrail tied to a key you own. With the default key, rotation is handled by AWS on its own schedule, and disentangling your usage from the shared managed key is messier.
How to fix it
Here's the catch that surprises most people: you cannot change the KMS key on an existing EFS file system. Encryption settings, including the key, are fixed at creation time. Fixing this check means creating a new file system encrypted with your CMK and migrating the data over.
Step 1: Create a customer-managed key for EFS
aws kms create-key \
--description "CMK for EFS encryption" \
--tags TagKey=Purpose,TagValue=efs-encryption \
--query 'KeyMetadata.KeyId' --output text
Give it a friendly alias so it's easy to reference:
aws kms create-alias \
--alias-name alias/efs-prod \
--target-key-id <key-id-from-previous-step>
Attach a scoped key policy that grants only the roles that actually mount the file system. Here's a starting point:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowKeyAdministration",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111122223333:role/kms-admins" },
"Action": [
"kms:Create*", "kms:Describe*", "kms:Enable*", "kms:List*",
"kms:Put*", "kms:Update*", "kms:Revoke*", "kms:Disable*",
"kms:Get*", "kms:Delete*", "kms:ScheduleKeyDeletion", "kms:CancelKeyDeletion"
],
"Resource": "*"
},
{
"Sid": "AllowEFSUse",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111122223333:role/efs-app-role" },
"Action": [
"kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*",
"kms:GenerateDataKey*", "kms:DescribeKey", "kms:CreateGrant"
],
"Resource": "*",
"Condition": {
"StringEquals": { "kms:ViaService": "elasticfilesystem.us-east-1.amazonaws.com" }
}
}
]
}
Note: The kms:ViaService condition ensures the key can only be used through EFS, so even if a role has the permission it can't repurpose the key for other services. The kms:CreateGrant action is required because EFS uses grants internally to access the key.
Enable automatic rotation:
aws kms enable-key-rotation --key-id <key-id>
Step 2: Create a new EFS file system with the CMK
aws efs create-file-system \
--encrypted \
--kms-key-id alias/efs-prod \
--performance-mode generalPurpose \
--throughput-mode bursting \
--tags Key=Name,Value=app-data-encrypted
Recreate the mount targets in the same subnets and security groups as the original so your application can reach the new file system.
Step 3: Migrate the data
AWS DataSync is the cleanest way to copy data between two EFS file systems while preserving permissions and timestamps. Create a DataSync task with the old file system as the source location and the new one as the destination, then run it.
Warning: DataSync transfers and EFS storage both incur cost. For large file systems, run an initial sync while the old system is live, then do a short maintenance window for a final delta sync to minimize downtime. Plan for the data transfer charges before kicking off a multi-terabyte copy.
For smaller file systems, mount both and copy directly:
# Mount both file systems on a temporary EC2 instance
sudo mount -t efs -o tls fs-OLD123:/ /mnt/old
sudo mount -t efs -o tls fs-NEW456:/ /mnt/new
# Copy preserving permissions, ownership, and timestamps
sudo rsync -avHAX --info=progress2 /mnt/old/ /mnt/new/
Step 4: Cut over and decommission
Update your application, ECS task definitions, or Kubernetes PersistentVolume definitions to point at the new file system ID. Validate, then remove the old file system.
Danger: Deleting an EFS file system is irreversible and destroys all data on it. Confirm the migration is complete and your application is verified against the new file system before running this. Take a final backup or snapshot via AWS Backup first.
# Delete mount targets first, then the file system
aws efs describe-mount-targets --file-system-id fs-OLD123 \
--query 'MountTargets[].MountTargetId' --output text \
| tr '\t' '\n' \
| xargs -n1 -I{} aws efs delete-mount-target --mount-target-id {}
aws efs delete-file-system --file-system-id fs-OLD123
How to prevent it from happening again
Since the key can only be set at creation, the only durable fix is to make CMK encryption the default in how you provision EFS. Bake it into your IaC and block anything that doesn't comply.
Terraform
resource "aws_kms_key" "efs" {
description = "CMK for EFS"
enable_key_rotation = true
deletion_window_in_days = 30
}
resource "aws_efs_file_system" "app" {
encrypted = true
kms_key_id = aws_kms_key.efs.arn
tags = {
Name = "app-data"
}
}
CloudFormation
{
"Resources": {
"AppFileSystem": {
"Type": "AWS::EFS::FileSystem",
"Properties": {
"Encrypted": true,
"KmsKeyId": { "Ref": "EfsCmk" }
}
}
}
}
Gate it in CI/CD with policy-as-code
Use a tool like Checkov, tfsec, or OPA to fail any pull request that creates an EFS file system without a CMK. A Checkov run is a one-liner:
checkov -d . --check CKV_AWS_184
For a custom OPA/Rego rule that rejects EFS without an explicit kms_key_id:
deny[msg] {
resource := input.resource.aws_efs_file_system[name]
not resource.kms_key_id
msg := sprintf("EFS '%s' must use a customer-managed KMS key", [name])
}
Tip: Pair the CI gate with an AWS Config rule (efs-encrypted-check plus a custom rule checking KeyManager) so drift gets caught at runtime too, not just at deploy time. Lensix continuously evaluates this for you and surfaces any file system that slips onto the default key, so you don't have to wire up Config rules by hand.
Use service control policies for org-wide enforcement
In AWS Organizations, an SCP can deny EFS creation that doesn't specify a CMK, stopping the problem before it reaches an account:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyEfsWithoutCmk",
"Effect": "Deny",
"Action": "elasticfilesystem:CreateFileSystem",
"Resource": "*",
"Condition": {
"Null": { "elasticfilesystem:Encrypted": "true" }
}
}
]
}
Best practices
- One CMK per workload or sensitivity tier. Don't share a single key across every file system. Separate keys give you finer-grained access control and a cleaner blast radius if one key needs to be disabled.
- Always enable key rotation. Annual rotation is free for CMKs and keeps you aligned with most compliance baselines.
- Scope key policies with
kms:ViaService. Lock the key to EFS so it can't be reused by an attacker who gains a role with KMS permissions. - Set a deletion window, not immediate deletion. A 30-day window on the CMK protects against accidental or malicious key deletion that would render your data unrecoverable.
- Monitor key usage in CloudTrail. Alert on unusual
Decryptvolume or calls from unexpected principals. - Encrypt at creation, every time. Because you can't add or change encryption later, treat unencrypted-or-default as a hard failure in your provisioning pipeline.
Moving off the default key is a one-time migration cost that buys you real control: the ability to write access policies, revoke during incidents, share across accounts, and satisfy auditors. Get your provisioning templates right once, gate them in CI, and new file systems will never land on the default key again.

