> ## 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.

# Ebs volume encryption remediation

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Using Console" defaultOpen="true">
        Below are step‑by‑step instructions using the AWS Management Console to ensure EC2 volumes are encrypted. There are two parts:

        1. Enable **default EBS encryption** for all new volumes
        2. Encrypt **existing unencrypted volumes**

        ***

        ## 1. Enable default EBS volume encryption (for all new volumes)

        1. Sign in to the AWS Management Console and go to **EC2**.
        2. In the left navigation pane, under **Elastic Block Store**, choose **Settings** (or **EBS encryption** depending on console version).
        3. Click **Manage** (or **Edit**).
        4. Check **Enable encryption by default**.
        5. (Optional) In **AWS KMS key**, choose a customer‑managed KMS key, or leave the default `aws/ebs`.
        6. Click **Save changes**.

        All **new** EBS volumes and snapshots created in this Region are now encrypted.

        ***

        ## 2. Encrypt an existing unencrypted EBS volume

        You cannot turn encryption on directly for an existing volume; you must migrate data to a new encrypted volume.

        ### 2.1 Identify the unencrypted volume

        1. In the **EC2** console, in the left pane choose **Volumes**.
        2. Add the **Encrypted** column (gear icon ▸ check **Encrypted**).
        3. Find volumes where **Encrypted = False** that you want to remediate.

        ***

        ### 2.2 Create a snapshot of the unencrypted volume

        1. Select the unencrypted volume.
        2. Click **Actions ▸ Create snapshot**.
        3. Enter a **Description** (e.g., `snapshot-before-encryption-vol-<id>`).
        4. Click **Create snapshot**.
        5. Go to **Snapshots** and wait until the snapshot’s **Status** is `completed`.

        ***

        ### 2.3 Copy the snapshot and enable encryption

        1. In **Snapshots**, select the snapshot you just created.
        2. Click **Actions ▸ Copy snapshot**.
        3. Keep the same **Region** (or choose another if needed).
        4. Under **Encryption**, check **Encrypt this snapshot**.
        5. Choose the **KMS key** (default `aws/ebs` or your CMK).
        6. Click **Copy snapshot**.
        7. Wait until the **copied** snapshot’s **Status** is `completed`.

        ***

        ### 2.4 Create an encrypted volume from the encrypted snapshot

        1. In **Snapshots**, select the **encrypted** snapshot (the copy).
        2. Click **Actions ▸ Create volume**.
        3. Choose:
           * **Availability Zone**: must match the AZ of the original volume’s attached instance (e.g., `us-east-1a`).
           * **Volume type** and **Size**: match the original volume (or larger).
        4. Ensure **Encrypted** is `Yes` and the correct **KMS key** is selected.
        5. Click **Create volume**.
        6. Wait until the new volume’s **State** is `available`.

        ***

        ### 2.5 Detach the old volume and attach the new encrypted volume

        > To avoid data loss, perform this during a maintenance window and back up first.

        1. In **EC2 ▸ Instances**, select the instance using the original unencrypted volume.

        2. Stop application services that write to the disk, then **stop the instance**:
           * **Instance state ▸ Stop instance** and confirm.

        3. After the instance is `stopped`, go to **Volumes**.

        4. Select the **old unencrypted** volume.

        5. Click **Actions ▸ Detach volume** and confirm.

        6. Note its **Device name** (e.g., `/dev/xvda`, `/dev/sdf`) for the next step.

        7. Select the **new encrypted** volume.

        8. Click **Actions ▸ Attach volume**.

        9. Choose the **Instance** and specify the **Device name** to match the old one.

        10. Click **Attach volume**.

        ***

        ### 2.6 Start the instance and validate

        1. Go back to **Instances**, select the instance.
        2. Click **Instance state ▸ Start instance**.
        3. Once running, log into the instance and validate:
           * Volumes and file systems mount correctly.
           * Applications run as expected.
        4. In **Volumes**, confirm the attached volume shows **Encrypted = True**.

        ***

        ### 2.7 (Optional) Clean up old unencrypted resources

        After you’ve confirmed everything works and backups are in place:

        1. In **Volumes**, select the **old unencrypted** volume.
        2. Click **Actions ▸ Delete volume** and confirm.
        3. In **Snapshots**, delete the **original unencrypted snapshot** if no longer needed.

        ***

        You can repeat steps 2.1–2.7 for each unencrypted EBS volume you need to remediate.
      </Accordion>

      <Accordion title="Using CLI">
        Below are the key ways to remediate “Enable Volume Encryption” for AWS EC2 using the AWS CLI.

        ***

        ## 1. Enable Default EBS Encryption (Global Setting)

        This ensures **all new** EBS volumes and snapshots created in this region are encrypted by default.

        ### 1.1. Check current default encryption status

        ```bash theme={null}
        aws ec2 get-ebs-encryption-by-default
        ```

        Look for `"EbsEncryptionByDefault": false` or `true`.

        ### 1.2. Enable default EBS encryption

        ```bash theme={null}
        aws ec2 enable-ebs-encryption-by-default
        ```

        (Optionally specify a custom KMS key)

        ```bash theme={null}
        aws ec2 modify-ebs-default-kms-key-id \
          --kms-key-id arn:aws:kms:<region>:<account-id>:key/<key-id>
        ```

        ***

        ## 2. Encrypt an Existing Unencrypted EBS Volume

        Existing volumes **cannot be encrypted in-place**; you must:

        1. Create an encrypted snapshot from it,
        2. Create a new encrypted volume from that snapshot,
        3. Stop the instance, swap volumes, and start the instance.

        Assume:

        * Region: `us-east-1`
        * Instance ID: `i-0123456789abcdef0`
        * Old volume ID: `vol-0123456789abcdef0`
        * Device name: `/dev/xvda` (root volume example)

        ### 2.1. Create a snapshot of the existing unencrypted volume

        ```bash theme={null}
        aws ec2 create-snapshot \
          --region us-east-1 \
          --volume-id vol-0123456789abcdef0 \
          --description "Snapshot before encryption"
        ```

        Note the `SnapshotId` returned, e.g. `snap-0123456789abcdef0`.

        Wait for snapshot completion:

        ```bash theme={null}
        aws ec2 describe-snapshots \
          --region us-east-1 \
          --snapshot-ids snap-0123456789abcdef0 \
          --query "Snapshots[0].State"
        ```

        Continue when state is `completed`.

        ### 2.2. Create an **encrypted** copy of the snapshot

        ```bash theme={null}
        aws ec2 copy-snapshot \
          --region us-east-1 \
          --source-region us-east-1 \
          --source-snapshot-id snap-0123456789abcdef0 \
          --encrypted \
          --description "Encrypted copy of snapshot"
        ```

        Optionally specify a KMS key:

        ```bash theme={null}
        aws ec2 copy-snapshot \
          --region us-east-1 \
          --source-region us-east-1 \
          --source-snapshot-id snap-0123456789abcdef0 \
          --encrypted \
          --kms-key-id arn:aws:kms:us-east-1:<account-id>:key/<key-id> \
          --description "Encrypted copy of snapshot"
        ```

        Note the new `SnapshotId` (e.g. `snap-0encrypted123456789`), and wait until it’s `completed` as above.

        ### 2.3. Create a new encrypted volume from the encrypted snapshot

        Get the Availability Zone of the current volume:

        ```bash theme={null}
        aws ec2 describe-volumes \
          --region us-east-1 \
          --volume-ids vol-0123456789abcdef0 \
          --query "Volumes[0].AvailabilityZone" \
          --output text
        ```

        Assume it returns `us-east-1a`.

        Create the encrypted volume:

        ```bash theme={null}
        aws ec2 create-volume \
          --region us-east-1 \
          --availability-zone us-east-1a \
          --snapshot-id snap-0encrypted123456789 \
          --volume-type gp3
        ```

        Note the new `VolumeId` (e.g. `vol-0encrypted123456789`) and wait until state is `available`:

        ```bash theme={null}
        aws ec2 describe-volumes \
          --region us-east-1 \
          --volume-ids vol-0encrypted123456789 \
          --query "Volumes[0].State"
        ```

        ### 2.4. Stop the instance

        ```bash theme={null}
        aws ec2 stop-instances \
          --region us-east-1 \
          --instance-ids i-0123456789abcdef0
        ```

        Wait until it’s stopped:

        ```bash theme={null}
        aws ec2 wait instance-stopped \
          --region us-east-1 \
          --instance-ids i-0123456789abcdef0
        ```

        ### 2.5. Detach the old (unencrypted) volume

        ```bash theme={null}
        aws ec2 detach-volume \
          --region us-east-1 \
          --volume-id vol-0123456789abcdef0
        ```

        Wait for it to become `available`.

        ### 2.6. Attach the new encrypted volume

        Attach using the same device name as before (e.g. `/dev/xvda`):

        ```bash theme={null}
        aws ec2 attach-volume \
          --region us-east-1 \
          --volume-id vol-0encrypted123456789 \
          --instance-id i-0123456789abcdef0 \
          --device /dev/xvda
        ```

        ### 2.7. Start the instance

        ```bash theme={null}
        aws ec2 start-instances \
          --region us-east-1 \
          --instance-ids i-0123456789abcdef0
        ```

        ***

        ## 3. Verify the Volume Is Encrypted

        ```bash theme={null}
        aws ec2 describe-volumes \
          --region us-east-1 \
          --volume-ids vol-0encrypted123456789 \
          --query "Volumes[0].{Encrypted:Encrypted,KmsKeyId:KmsKeyId}"
        ```

        You should see `"Encrypted": true`.

        ***

        If you share:

        * region,
        * instance ID,
        * which volume(s) (root vs data),
          I can tailor exact command sequences for each.
      </Accordion>

      <Accordion title="Using Python">
        Below are concrete remediation steps and a Python (boto3) example to enable EBS volume encryption for EC2 in AWS.

        ***

        ## 1. Prerequisites

        1. Install and configure AWS CLI or set environment variables so boto3 can authenticate:
           ```bash theme={null}
           pip install boto3
           aws configure  # or set AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_REGION
           ```

        2. Make sure your IAM principal has:
           * `ec2:DescribeVolumes`
           * `ec2:ModifyVolume`
           * `ec2:DescribeInstances`
           * `ec2:EnableEbsEncryptionByDefault` (if you also want to turn on default encryption)
           * Permissions to use the chosen KMS key (`kms:Encrypt`, `kms:Decrypt`, etc.).

        ***

        ## 2. One-time: Enable EBS encryption by default (recommended)

        This makes all *new* EBS volumes encrypted automatically.

        ```python theme={null}
        import boto3

        region = "us-east-1"
        ec2 = boto3.client("ec2", region_name=region)

        response = ec2.enable_ebs_encryption_by_default()
        print("EBS encryption by default enabled:", response["EbsEncryptionByDefault"])
        ```

        ***

        ## 3. Encrypt existing unencrypted EBS volumes in-place

        AWS now supports converting an unencrypted EBS volume to encrypted using `modify_volume`.

        ### High-level steps

        1. List all volumes (optionally filter by instance, tags, region).
        2. For each volume:
           * Skip if `Encrypted` is `True`.
           * Call `ModifyVolume` with `Encrypted=True` and optional `KmsKeyId`.
           * Poll `DescribeVolumesModifications` until the modification state is `completed` or `optimizing`.

        ### Important notes

        * This operation is online: the instance can remain running.
        * Performance may be slightly impacted while the volume is being optimized.
        * Choose a CMK if your security policy requires customer-managed keys; otherwise, AWS-managed key is fine.

        ***

        ## 4. Example Python script (boto3)

        This example:

        * Targets a specific region.
        * Optionally targets a specific instance by ID (or all volumes in the region).
        * Encrypts all unencrypted volumes with the default EBS KMS key (or a specific CMK if provided).

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

        REGION = "us-east-1"
        INSTANCE_ID = None  # set to an EC2 instance ID like "i-0123456789abcdef0" or leave as None for all volumes in the region
        KMS_KEY_ID = None   # e.g. "arn:aws:kms:us-east-1:123456789012:key/abcd-..." or leave None to use AWS-managed key

        ec2 = boto3.client("ec2", region_name=REGION)


        def get_target_volumes(instance_id=None):
            filters = []
            if instance_id:
                filters.append({"Name": "attachment.instance-id", "Values": [instance_id]})

            paginator = ec2.get_paginator("describe_volumes")
            volumes = []
            for page in paginator.paginate(Filters=filters):
                for vol in page["Volumes"]:
                    if not vol["Encrypted"]:
                        volumes.append(vol)
            return volumes


        def encrypt_volume(volume_id, kms_key_id=None):
            params = {
                "VolumeId": volume_id,
                "Encrypted": True,
            }
            if kms_key_id:
                params["KmsKeyId"] = kms_key_id

            print(f"Starting encryption for volume {volume_id} ...")
            ec2.modify_volume(**params)


        def wait_for_encryption(volume_id, timeout=3600, poll_interval=15):
            """Wait until volume modification is completed or optimizing."""
            start = time.time()
            while True:
                resp = ec2.describe_volumes_modifications(VolumeIds=[volume_id])
                mods = resp.get("VolumesModifications", [])
                if not mods:
                    print(f"No modification record for volume {volume_id}, assuming done.")
                    return

                mod = mods[0]
                state = mod["ModificationState"]
                progress = mod.get("Progress", 0)
                print(f"Volume {volume_id} state={state}, progress={progress}%")

                if state in ("completed", "optimizing"):
                    print(f"Encryption finished/optimizing for volume {volume_id}.")
                    return

                if time.time() - start > timeout:
                    raise TimeoutError(f"Timeout waiting for volume {volume_id} encryption")

                time.sleep(poll_interval)


        def main():
            # 1. Enable EBS encryption by default for new volumes (optional but recommended)
            try:
                resp = ec2.enable_ebs_encryption_by_default()
                print("EBS encryption by default:", resp["EbsEncryptionByDefault"])
            except ec2.exceptions.ClientError as e:
                print("Could not enable EBS encryption by default (check perms):", e)

            # 2. Find all unencrypted volumes (optionally only for one instance)
            vols = get_target_volumes(INSTANCE_ID)
            if not vols:
                print("No unencrypted volumes found.")
                return

            print(f"Found {len(vols)} unencrypted volumes.")
            for v in vols:
                vol_id = v["VolumeId"]
                print(f"Processing volume {vol_id} (size={v['Size']}GiB, type={v['VolumeType']})")

                # 3. Start encryption
                try:
                    encrypt_volume(vol_id, KMS_KEY_ID)
                except ec2.exceptions.ClientError as e:
                    print(f"Failed to start encryption for {vol_id}: {e}")
                    continue

                # 4. Wait until encryption is done/optimizing
                try:
                    wait_for_encryption(vol_id)
                except Exception as e:
                    print(f"Error waiting for encryption of {vol_id}: {e}")


        if __name__ == "__main__":
            main()
        ```

        ***

        ## 5. What to adjust for your environment

        * Set `REGION` to your AWS region.
        * Set `INSTANCE_ID` if you only want to remediate a single instance.
        * Set `KMS_KEY_ID` to a CMK if required by policy.
        * Optionally narrow scopes using tags via `Filters` in `describe_volumes`.

        This is sufficient to remediate the “Enable Volume Encryption” finding for EC2 EBS volumes using Python on AWS.
      </Accordion>

      <Accordion title="Using Terraform">
        ```hcl theme={null}
        # Encrypt all new EBS volumes in this account/region by default
        resource "aws_ebs_encryption_by_default" "default" {
          enabled = true
        }

        # (Optional) Use a specific KMS key instead of aws/ebs
        # Replace KMS_KEY_ARN with your KMS key ARN (e.g. arn:aws:kms:us-east-1:123456789012:key/abc-...)
        resource "aws_ebs_default_kms_key" "default" {
          key_arn = "KMS_KEY_ARN"
        }

        # Example: encrypted standalone EBS volume
        # NOTE: Turning on `encrypted` for an existing, unmanaged-by-Terraform volume
        # requires creating a new encrypted volume and migrating data; Terraform can’t
        # flip encryption in-place.
        resource "aws_ebs_volume" "encrypted_data" {
          availability_zone = "AVAILABILITY_ZONE" # e.g. us-east-1a
          size              = 100

          encrypted = true
          kms_key_id = aws_ebs_default_kms_key.default.key_arn # or omit to use aws/ebs
          tags = {
            Name = "ENCRYPTED_VOLUME_NAME"
          }
        }

        # Example: encrypt the root volume of a new EC2 instance via a launch template
        resource "aws_launch_template" "encrypted" {
          name_prefix   = "ENCRYPTED_LT_NAME_PREFIX"
          image_id      = "AMI_ID"
          instance_type = "t3.micro"

          block_device_mappings {
            device_name = "/dev/xvda"

            ebs {
              volume_size = 20
              encrypted   = true
              kms_key_id  = aws_ebs_default_kms_key.default.key_arn
              volume_type = "gp3"
            }
          }
        }
        ```

        Enabling `aws_ebs_encryption_by_default` is in-place; adding `encrypted = true` (and optionally `kms_key_id`) on `aws_ebs_volume` or launch templates causes new encrypted volumes to be created instead of unencrypted ones. For already-existing unencrypted volumes, Terraform must create new encrypted volumes and you must handle cutover; encryption cannot be toggled in-place.

        After remediation, `terraform plan` should show:

        * `aws_ebs_encryption_by_default.default` created with `enabled = true`.
        * (Optional) `aws_ebs_default_kms_key.default` created with your KMS key ARN.
        * Any `aws_ebs_volume` or launch template changes adding `encrypted = true` (and `kms_key_id`), with volume resources marked for replacement where applicable.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
