> ## Documentation Index
> Fetch the complete documentation index at: https://cloudanix.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# AWS KMS Customer Master Keys Should Be Used For EFS Encryption

### More Info:

Ensure that your Amazon EFS file systems are encrypted using KMS CMK customer-managed keys instead of AWS managed-keys (default keys used by the EFS service when there are no customer keys defined) in order to have more granular control over your data-at-rest encryption/decryption process.

### Risk Level

High

### Address

Security

### Compliance Standards

ISO27001,HIPAA

### Remediation

### Triage and Remediation

<Tabs>
  <Tab title="Remediation">
    ### Remediation

    <AccordionGroup>
      <Accordion title="Using Console" defaultOpen="true">
        The setting “KMS Customer Master Keys Should Be Used For EFS Encryption” applies to Amazon EFS, not API Gateway. Below are the remediation steps using the AWS Management Console for **EFS**. (API Gateway doesn’t store data on EFS directly.)

        ### 1. Check your existing EFS encryption

        1. Sign in to the AWS Management Console.
        2. Go to **Amazon EFS**.
        3. In **File systems**, look at your existing file systems:
           * Column **Encrypted** shows if it’s encrypted.
           * Click a file system → **General** tab → check **KMS key**.\
             If it says “aws/elasticfilesystem” or “Not encrypted”, you need to move to a file system using a customer-managed KMS key.

        > Note: You cannot turn encryption on or change the KMS key for an existing EFS file system. You must create a new encrypted file system and migrate data.

        ***

        ### 2. Create a customer-managed KMS key (CMK)

        1. Open the **AWS Key Management Service (KMS)** console.
        2. In the left menu, choose **Customer managed keys** → **Create key**.
        3. **Key type**: Symmetric.
        4. **Key usage**: Encrypt and decrypt.
        5. **Key material origin**: KMS (default).
        6. Click **Next** and configure:
           * **Alias**: e.g., `alias/efs-prod`.
           * **Description**: e.g., `Customer-managed CMK for EFS encryption`.
        7. On the **Key administrators** step, select IAM roles/users who can manage this key.
        8. On the **Key users** step, add:
           * Any IAM roles/instances/Lambda functions/ECS tasks that will mount and use the EFS.
        9. Finish the wizard with **Create key**.

        Make sure you create the key in the **same region** as your EFS.

        ***

        ### 3. Create a new EFS file system encrypted with your CMK

        1. Go back to the **Amazon EFS** console.
        2. Click **Create file system**.
        3. Choose the same **VPC** and **Availability Zones** as your existing file system.
        4. Click **Customize** so you can edit encryption settings.
        5. Under **General settings**:
           * **Encryption**: Make sure **Enable encryption of data at rest** is checked.
           * **KMS key**: From the dropdown, select your customer-managed key (e.g., `alias/efs-prod`).
        6. Configure **Network** settings (subnets, security groups) to match your existing EFS as closely as possible.
        7. Configure **Performance** and **Throughput** as needed.
        8. Click **Create**.

        Now you have a new EFS file system encrypted with a customer-managed KMS key.

        ***

        ### 4. Migrate data from old EFS to new EFS

        For each environment (e.g., EC2 instances, container tasks):

        1. On a Linux instance that has network access to both file systems:
           * Mount the **old** EFS:
             ```bash theme={null}
             sudo mkdir /mnt/old-efs /mnt/new-efs
             sudo mount -t efs fs-OLD_ID:/ /mnt/old-efs
             ```
           * Mount the **new** EFS:
             ```bash theme={null}
             sudo mount -t efs fs-NEW_ID:/ /mnt/new-efs
             ```
        2. Copy data:
           ```bash theme={null}
           sudo rsync -aHAX --delete /mnt/old-efs/ /mnt/new-efs/
           ```
        3. Verify data and permissions in `/mnt/new-efs`.

        (If you use EFS Access Points, recreate them on the new file system first, then mount via those access points and copy.)

        ***

        ### 5. Update applications to use the new EFS

        1. Update **mount targets** in:
           * EC2 `fstab` entries.
           * Auto Scaling/user data scripts.
           * ECS task definitions (EFS volume config).
           * EKS/containers (PersistentVolume definitions).
           * Lambda EFS configuration.
        2. Replace `fs-OLD_ID` with `fs-NEW_ID` (or the new access point).
        3. Roll out the changes so all clients mount the **new** encrypted file system.
        4. Confirm that workloads function normally and write/read from the new EFS.

        ***

        ### 6. Decommission the old unencrypted / KMS-default EFS

        1. Once migration is validated and no clients use the old file system:
           * In the **EFS** console, select the old file system.
           * Click **Delete** and confirm.
        2. Optionally, set a **backup / snapshot retention** policy for the new EFS (via AWS Backup).

        ***

        ### 7. (Optional) Prevent future misconfigurations

        * Use **Service Control Policies (SCPs)** or **EFS resource policies** to:
          * Deny creation of EFS file systems without encryption.
          * Deny use of the default AWS-managed KMS key for EFS, forcing a customer-managed key.
        * In AWS Config or your security tool, enable the rule that checks EFS encryption and KMS key type.

        If you meant a different resource (e.g., API Gateway logging encryption with KMS), specify that and I’ll give steps for that particular service.
      </Accordion>

      <Accordion title="Using CLI">
        Here’s how to remediate “AWS KMS Customer Master Keys should be used for EFS encryption” using AWS CLI (as you might be doing via API-driven automation such as from an API Gateway–triggered function).

        AWS EFS **cannot change** its KMS key after creation. Remediation is:

        1. Create a customer-managed KMS key.
        2. Create a new EFS file system encrypted with that CMK.
        3. Migrate data from the old EFS to the new one.
        4. Switch your applications to the new EFS and delete the old one.

        Below are step-by-step CLI commands.

        ***

        ## 1. Create a customer-managed KMS key (CMK)

        ```bash theme={null}
        aws kms create-key \
          --description "CMK for EFS encryption" \
          --key-usage ENCRYPT_DECRYPT \
          --origin AWS_KMS \
          --region us-east-1
        ```

        Note the `KeyId` from the output.

        Optional: add a friendly alias:

        ```bash theme={null}
        aws kms create-alias \
          --alias-name alias/efs-cmk \
          --target-key-id <your-key-id> \
          --region us-east-1
        ```

        You can use either `alias/efs-cmk` or the KeyId/ARN in later steps.

        ***

        ## 2. Create a new EFS file system encrypted with the CMK

        ```bash theme={null}
        aws efs create-file-system \
          --creation-token my-efs-with-cmk \
          --performance-mode generalPurpose \
          --encrypted \
          --kms-key-id alias/efs-cmk \
          --region us-east-1
        ```

        Capture the returned `FileSystemId`, e.g. `fs-1234567890abcdef0`.

        Create one or more mount targets in your VPC subnets:

        ```bash theme={null}
        aws efs create-mount-target \
          --file-system-id fs-1234567890abcdef0 \
          --subnet-id subnet-abc123 \
          --security-groups sg-xyz789 \
          --region us-east-1
        ```

        Repeat `create-mount-target` for each AZ/subnet where you need mounts.

        ***

        ## 3. Migrate data from old EFS to new EFS

        On an EC2 instance that can reach both file systems:

        1. Mount the old (unencrypted or AWS-managed-key) EFS:
           ```bash theme={null}
           sudo mkdir -p /mnt/old-efs /mnt/new-efs
           sudo mount -t efs fs-OLDID:/ /mnt/old-efs
           sudo mount -t efs fs-1234567890abcdef0:/ /mnt/new-efs
           ```

        2. Copy data (example using `rsync`):
           ```bash theme={null}
           sudo rsync -aHAXx --numeric-ids /mnt/old-efs/ /mnt/new-efs/
           ```

        3. Update any application configs (e.g., EC2 user data, fstab, ECS task definitions, EKS PersistentVolumes, etc.) to point to the **new** EFS `fs-1234567890abcdef0`.

        ***

        ## 4. Remove the old EFS

        After verifying everything works on the new file system:

        1. Unmount on instances:
           ```bash theme={null}
           sudo umount /mnt/old-efs
           ```

        2. Delete mount targets:
           ```bash theme={null}
           aws efs describe-mount-targets \
             --file-system-id fs-OLDID \
             --region us-east-1 \
             --query 'MountTargets[].MountTargetId' \
             --output text | xargs -n1 -I {} \
               aws efs delete-mount-target --mount-target-id {} --region us-east-1
           ```

        3. Delete the old file system:
           ```bash theme={null}
           aws efs delete-file-system \
             --file-system-id fs-OLDID \
             --region us-east-1
           ```

        ***

        ## 5. (Optional) Automating via API Gateway

        If your question refers to doing this *via* API Gateway:

        * Put these `aws` CLI–equivalent operations in a Lambda function (or other service) using AWS SDK.
        * Expose that Lambda via API Gateway.
        * The runtime code will call:
          * `CreateKey`, `CreateAlias` (KMS)
          * `CreateFileSystem`, `CreateMountTarget`, `DescribeMountTargets`, `DeleteMountTarget`, `DeleteFileSystem` (EFS)

        But the security remediation itself is exactly the steps above: ensure every EFS is created with `--encrypted` and `--kms-key-id` referencing a customer-managed CMK.
      </Accordion>

      <Accordion title="Using Python">
        To meet the control “AWS KMS Customer Master Keys Should Be Used For EFS Encryption” you need:

        1. An AWS KMS CMK (customer-managed key)
        2. EFS file systems encrypted at rest with that CMK
        3. A migration plan for any existing EFS that are either:
           * not encrypted, or
           * encrypted with `aws/elasticfilesystem` instead of your CMK

        You mentioned API Gateway and Python: typically you’d expose a remediation Lambda behind API Gateway that runs the Python/boto3 logic below. I’ll focus on the remediation logic in Python; you can attach it to API Gateway as needed.

        ***

        ## 1. Create (or identify) a KMS CMK for EFS

        You can either use an existing CMK or create a new one.

        ### a) Create a CMK via boto3 (Python)

        ```python theme={null}
        import boto3

        kms = boto3.client('kms', region_name='us-east-1')

        response = kms.create_key(
            Description='CMK for EFS encryption',
            KeyUsage='ENCRYPT_DECRYPT',
            Origin='AWS_KMS',
            Tags=[
                {'TagKey': 'Name', 'TagValue': 'efs-cmk'},
                {'TagKey': 'SecurityControl', 'TagValue': 'EFS-KMS'}
            ]
        )

        cmk_id = response['KeyMetadata']['KeyId']
        print("Created CMK:", cmk_id)
        ```

        Optionally create an alias:

        ```python theme={null}
        kms.create_alias(
            AliasName='alias/efs-cmk',
            TargetKeyId=cmk_id
        )
        ```

        You can now refer to this key as `alias/efs-cmk` (recommended) instead of the raw key ID.

        ***

        ## 2. Create new EFS with CMK encryption (compliant going forward)

        For **any new** EFS, you must specify both `Encrypted=True` and the `KmsKeyId`:

        ```python theme={null}
        import boto3

        efs = boto3.client('efs', region_name='us-east-1')

        response = efs.create_file_system(
            CreationToken='my-efs-creation-token',
            Encrypted=True,
            KmsKeyId='alias/efs-cmk',  # or cmk_id from above
            PerformanceMode='generalPurpose',
            Tags=[
                {'Key': 'Name', 'Value': 'my-encrypted-efs'},
                {'Key': 'SecurityControl', 'Value': 'EFS-KMS'}
            ]
        )

        file_system_id = response['FileSystemId']
        print("Created EFS:", file_system_id)
        ```

        This EFS is now encrypted using your CMK and will satisfy the control.

        ***

        ## 3. Handle existing non-compliant EFS file systems

        Important limitation:\
        **You cannot change encryption or KMS key of an existing EFS file system.**\
        Remediation requires **creating a new encrypted EFS and migrating data**.

        ### a) Detect non‑compliant EFS (not using CMK)

        ```python theme={null}
        import boto3

        efs = boto3.client('efs', region_name='us-east-1')

        def list_non_compliant_efs(target_kms_alias='alias/efs-cmk'):
            paginator = efs.get_paginator('describe_file_systems')
            non_compliant = []

            for page in paginator.paginate():
                for fs in page['FileSystems']:
                    fs_id = fs['FileSystemId']
                    encrypted = fs.get('Encrypted', False)
                    kms_id = fs.get('KmsKeyId')

                    # Not encrypted at all
                    if not encrypted:
                        non_compliant.append((fs_id, 'UNENCRYPTED'))
                        continue

                    # Encrypted but not with our CMK (e.g. aws/elasticfilesystem)
                    if kms_id and target_kms_alias not in kms_id:
                        non_compliant.append((fs_id, f'WRONG_KMS: {kms_id}'))

            return non_compliant

        print(list_non_compliant_efs('alias/efs-cmk'))
        ```

        You may instead check specifically for the AWS-managed key `aws/elasticfilesystem` by inspecting `KmsKeyId`, but the above shows the pattern.

        ### b) Remediation pattern for each non‑compliant EFS

        The high‑level steps (manual or automated):

        1. **Create new compliant EFS** using the CMK (from step 2).
        2. **Mount both file systems** on a temporary EC2 instance (or use AWS DataSync).
        3. **Copy data** from old to new EFS (`rsync`, `cp`, DataSync task, etc.).
        4. **Update clients** (EC2, ECS, EKS, Lambda, etc.) to mount the new EFS.
        5. **Validate** application behavior.
        6. **Delete old non‑compliant EFS** when safe.

        You can orchestrate parts of this with Python, but the data copy is typically OS‑level or DataSync‑based, not pure boto3.

        Example: creating a “replacement” EFS for each non‑compliant file system:

        ```python theme={null}
        def create_replacement_efs(old_fs_id, kms_alias='alias/efs-cmk'):
            # You can copy tags, performance mode, etc. from the old FS if desired
            old_details = efs.describe_file_systems(FileSystemId=old_fs_id)['FileSystems'][0]

            response = efs.create_file_system(
                CreationToken=f'replacement-for-{old_fs_id}',
                Encrypted=True,
                KmsKeyId=kms_alias,
                PerformanceMode=old_details['PerformanceMode'],
                ThroughputMode=old_details.get('ThroughputMode', 'bursting'),
                Tags=[
                    {'Key': 'Name', 'Value': f'replacement-{old_fs_id}'},
                    {'Key': 'Replaces', 'Value': old_fs_id},
                    {'Key': 'SecurityControl', 'Value': 'EFS-KMS'}
                ]
            )
            return response['FileSystemId']
        ```

        Then handle mounts + data copy outside of this script.

        ***

        ## 4. Exposing this via API Gateway (optional)

        If you want this to be triggered **via API Gateway**:

        1. Create a **Lambda function** with the Python code above (or a subset that:
           * checks for non‑compliant EFS, and/or
           * creates compliant EFS).
        2. Give Lambda an IAM role with:
           * `kms:CreateKey`, `kms:DescribeKey`, `kms:CreateAlias` (if creating CMKs),
           * `elasticfilesystem:DescribeFileSystems`, `elasticfilesystem:CreateFileSystem`, `elasticfilesystem:DescribeTags`, `elasticfilesystem:CreateTags`.
        3. Create an **API Gateway REST API or HTTP API** that:
           * Integrates a route (e.g. `POST /remediate-efs-kms`) with this Lambda.
        4. Call that API to perform the remediation.

        Your Lambda handler might look like:

        ```python theme={null}
        import json
        import boto3

        efs = boto3.client('efs')
        kms_alias = 'alias/efs-cmk'

        def lambda_handler(event, context):
            non_compliant = list_non_compliant_efs(kms_alias)
            replacements = []

            for fs_id, reason in non_compliant:
                new_fs_id = create_replacement_efs(fs_id, kms_alias)
                replacements.append({
                    'old_fs_id': fs_id,
                    'new_fs_id': new_fs_id,
                    'reason': reason
                })

            return {
                'statusCode': 200,
                'body': json.dumps({
                    'non_compliant_count': len(non_compliant),
                    'replacements_created': replacements
                })
            }
        ```

        This does the **infrastructure** part of remediation; you still must handle the data copy and cutover.

        ***

        If you clarify whether you want:

        * only detection,
        * detection + new EFS creation, or
        * a fully automated flow with DataSync and mount updates,

        I can provide a tighter, ready-to-deploy script or Lambda function.
      </Accordion>

      <Accordion title="Using Terraform">
        ```hcl theme={null}
        resource "aws_efs_file_system" "THIS_EFS" {
          # Replace THIS_EFS with your EFS identifier (e.g., APP_EFS)

          creation_token = "THIS_EFS_CREATION_TOKEN" # replace with a stable unique token for this filesystem

          # Ensure EFS is encrypted with a customer-managed KMS key
          encrypted  = true
          kms_key_id = aws_kms_key.EFS_KMS_KEY.arn
        }

        resource "aws_kms_key" "EFS_KMS_KEY" {
          description             = "KMS CMK for encrypting EFS file system THIS_EFS"
          deletion_window_in_days = 30
          enable_key_rotation     = true
        }
        ```

        Substitute:

        * `THIS_EFS` with your EFS Terraform name.
        * `THIS_EFS_CREATION_TOKEN` with a unique, stable string for this filesystem (or re-use your existing one if already managed).
        * Adjust the `aws_kms_key` block if you already manage a CMK (in that case, reference that key instead of creating a new one).

        Changing `encrypted` from false to true or changing `kms_key_id` on an existing `aws_efs_file_system` forces replacement of the EFS file system, which is disruptive and can cause data loss if not migrated first.

        To verify, `terraform plan` should show:

        * `encrypted` set to `true`.
        * `kms_key_id` set to the ARN of the customer-managed KMS key (and no remaining use of the AWS-managed default key).
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
