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

# OCI Storage Boot Volumes Should Be Encrypted With Customer-Managed Keys

### More Info:

Boot volumes should be encrypted using Customer-Managed Keys (CMKs) to ensure operating system level data at rest is secured with keys controlled exclusively by your organizations security administrators

### Risk Level

High

### Address

Compliance, Security

### Compliance Standards

* APRA CPS 234 (Australia)
* AWS Well Architected Framework
* BSI C5 (Germany)
* Brazil LGPD
* CCPA / CPRA (California)
* CIS Critical Security Controls v8
* CMMC 2.0
* CSA Cloud Controls Matrix v4
* DPDPA
* Digital Operational Resilience Act (EU)
* Essential 8
* HITRUST CSF
* ISO/IEC 27017
* ISO/IEC 27018
* ISO/IEC 27701
* KSA PDPL
* MAS Technology Risk Management (Singapore)
* MITRE ATT\&CK (Cloud)
* NIS2 Directive
* NIST
* NIST CSF
* NIST SP 800-171
* NYDFS 23 NYCRR 500
* PCI
* SOC2
* SWIFT Customer Security Controls Framework
* Sarbanes-Oxley IT General Controls
* Securities and Exchange Board of India (SEBI) - Cloud Security Adoption Framework
* UK NCSC Cyber Assessment Framework

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Using Console" defaultOpen="true">
        Here’s how to remediate “Boot Volumes Should Be Encrypted with Customer‑Managed Keys (CMKs)” using the OCI Console.

        ***

        ## 1. Create a Vault and a Customer-Managed Key (CMK)

        1. In the OCI Console, open the navigation menu.
        2. Go to **Identity & Security → Vault**.
        3. Choose the **compartment** where you want the vault.
        4. Click **Create vault**:
           * Name: e.g., `boot-volume-vault`
           * Vault type: **Default** or **Virtual Private**
           * Click **Create vault**.
        5. After the vault is active, click it.
        6. Go to **Master Encryption Keys → Create key**:
           * Protection mode: **HSM** or **Software** (per your policy)
           * Key shape: key algorithm and length (e.g., AES-256)
           * Name: e.g., `boot-volume-cmk`
           * Click **Create key**.

        ***

        ## 2. Ensure Block Storage Can Use the Key

        If needed, add a policy so Block Volume can use the key (in the tenancy root or relevant compartment):

        1. Go to **Identity & Security → Policies**.

        2. Choose the compartment where you manage policies (often **root**).

        3. Click **Create policy** or edit an existing one.

        4. Add a statement like (adjust compartments/OCID as needed):

           ```text theme={null}
           Allow service blockstorage in tenancy to use keys in compartment <vault-compartment-name>
           ```

        5. Save the policy.

        ***

        ## 3. Use CMK for New Boot Volumes (Going Forward)

        For all new compute instances / boot volumes:

        1. Go to **Compute → Instances → Create instance**.
        2. Configure instance details as usual.
        3. In the **Boot volume** section:
           * Expand **Show advanced options**.
           * For **Encryption**, choose **Encrypt using customer-managed keys**.
           * Select the **Vault** and **Key** you created (`boot-volume-vault` / `boot-volume-cmk`).
        4. Complete instance creation.

        All newly created boot volumes will now be encrypted with your CMK.

        ***

        ## 4. Migrate Existing Boot Volumes to CMK Encryption

        You cannot just “flip” the key on an existing boot volume; you must create a new boot volume encrypted with the CMK and then move the workload.

        ### 4.1. Create a Backup of the Existing Boot Volume

        1. Go to **Compute → Instances**.
        2. Click the instance whose boot volume isn’t using a CMK.
        3. Under **Resources**, click **Boot volume** to open it (or note the boot volume name, then go to **Block Storage → Boot volumes** and open it).
        4. In the boot volume page, click **Create backup**:
           * Name: e.g., `bv-backup-cmk-migration-<date>`
           * Click **Create backup**.
        5. Wait until the backup is in **Available** state.

        ### 4.2. Create a New Boot Volume from the Backup with CMK

        1. Go to **Block Storage → Boot volume backups**.
        2. Open the backup you just created.
        3. Click **Create boot volume**.
        4. In the dialog:
           * Select **Compartment** (same as instance, typically).
           * Under **Encryption**, choose **Encrypt using customer-managed keys**.
           * Select your **Vault** and **Key** (`boot-volume-cmk`).
        5. Click **Create boot volume** and wait until it becomes **Available**.

        ### 4.3. Replace the Old Boot Volume on the Instance

        This requires some downtime.

        1. Go to **Compute → Instances** and open the instance.
        2. Click **Stop** (graceful shutdown) and wait until the instance state is **Stopped**.
        3. Under **Resources → Boot volume attachments**, note the current attachment, then **Detach** the existing boot volume.
        4. Click **Attach boot volume**:
           * Select the **new** CMK-encrypted boot volume.
           * Attachment type: **Paravirtualized** or **iSCSI** as before.
           * Device path: leave default unless you have a specific requirement.
        5. Save/attach it.

        If OCI does not allow directly attaching a different boot volume as “boot” in your region/shape, use this alternative:

        * **Alternative**:
          1. From **Block Storage → Boot volumes**, locate the new CMK-encrypted boot volume.
          2. Click **Create instance** from this boot volume.
          3. Configure the new instance to match the old one (shape, VCN/subnet, etc.).
          4. Redirect traffic (update DNS, load balancer backend set, or IPs) from old instance to new instance.
          5. Decommission the old instance and its non‑CMK boot volume when confirmed.

        ***

        ## 5. Clean Up and Confirm Compliance

        1. Once the instance is confirmed working on the new CMK-encrypted boot volume, delete the old non‑CMK boot volume and any unnecessary backups.
        2. To confirm:
           * Go to **Block Storage → Boot volumes**, open the volume.
           * Check the **Encryption** section; it should show the **Customer-managed key** and its OCID.
        3. Re-run your **OCI Security/Compliance/Monitoring** check (e.g., Cloud Guard target or external CSPM tool) and verify that:
           * “Boot Volumes Should Be Encrypted with Customer-Managed Keys” is now passing for the compartment/tenancy.

        ***

        If you share your tenancy structure and how you’re monitoring (OCI Cloud Guard, Security Zones, or third-party CSPM), I can give a minimal, tailored checklist to verify this at scale.
      </Accordion>

      <Accordion title="Using CLI">
        Below is a concise, step-by-step way to remediate **“OCI Storage Boot Volumes Should Be Encrypted With Customer-Managed Keys”** using the **OCI CLI**.

        Assumptions:

        * You already have `oci` CLI configured with appropriate permissions.
        * You have (or will create) a Vault and a Key in OCI KMS.

        ***

        ## 1. Create (or identify) a Customer-Managed KMS Key

        ### 1.1 Find your vault

        ```bash theme={null}
        oci kms management vault list \
          --compartment-id <COMPARTMENT_OCID>
        ```

        Note the `id` of the vault you want to use.

        ### 1.2 List keys in that vault

        ```bash theme={null}
        oci kms management key list \
          --compartment-id <COMPARTMENT_OCID> \
          --vault-id <VAULT_OCID>
        ```

        If a suitable key exists, note its `id` (`<KEY_OCID>`).

        ### 1.3 (Optional) Create a new key

        ```bash theme={null}
        oci kms management key create \
          --compartment-id <COMPARTMENT_OCID> \
          --vault-id <VAULT_OCID> \
          --display-name "boot-volume-cmk" \
          --protection-mode HSM \
          --key-shape '{"algorithm": "AES", "length": 256}'
        ```

        From the output, note `"id"` → this is your `<KEY_OCID>`.

        ***

        ## 2. Ensure IAM Policy Lets Block Storage Use the Key

        Create a policy in the key’s compartment (or root) so Block Volume service can use it:

        Example policy statement:

        ```text theme={null}
        Allow service blockstorage to use keys in compartment <COMPARTMENT_NAME>
        ```

        If using CLI to create the policy:

        ```bash theme={null}
        oci iam policy create \
          --name "blockstorage-use-kms-key" \
          --compartment-id <TENANCY_OR_COMPARTMENT_OCID> \
          --statements '["Allow service blockstorage to use keys in compartment <COMPARTMENT_NAME>"]' \
          --description "Allow Block Volume service to use KMS CMKs"
        ```

        Replace `<COMPARTMENT_NAME>` accordingly.

        ***

        ## 3. Identify Boot Volumes to Fix

        List instances (optional):

        ```bash theme={null}
        oci compute instance list \
          --compartment-id <COMPARTMENT_OCID>
        ```

        For a given instance, get its boot volume attachment:

        ```bash theme={null}
        oci compute boot-volume-attachment list \
          --compartment-id <COMPARTMENT_OCID> \
          --instance-id <INSTANCE_OCID>
        ```

        From the output, note `"bootVolumeId"` → `<BOOT_VOLUME_OCID>`.

        You can also list all boot volumes directly:

        ```bash theme={null}
        oci bv boot-volume list \
          --compartment-id <COMPARTMENT_OCID>
        ```

        ***

        ## 4. Reconfigure Boot Volume to Use Customer-Managed Key

        You can update the boot volume to use the CMK:

        ```bash theme={null}
        oci bv boot-volume update \
          --boot-volume-id <BOOT_VOLUME_OCID> \
          --kms-key-id <KEY_OCID>
        ```

        This will re-encrypt the boot volume with the specified KMS CMK.

        Repeat for each non-compliant boot volume.

        ***

        ## 5. (Optional) Set CMK at Instance Launch / Instance Configuration

        For new instances (to prevent future drift), use `--kms-key-id` at launch:

        ```bash theme={null}
        oci compute instance launch \
          --compartment-id <COMPARTMENT_OCID> \
          --display-name "my-instance" \
          --availability-domain "<AD_NAME>" \
          --shape "<SHAPE_NAME>" \
          --source-details '{
            "sourceType": "image",
            "imageId": "<IMAGE_OCID>",
            "kmsKeyId": "<KEY_OCID>"
          }'
        ```

        For instance configurations (used by Instance Pools), include `kmsKeyId` under `instanceDetails -> blockVolumes` or `launchDetails` depending on your template.

        ***

        ## 6. Verify Encryption Status

        Check the boot volume details:

        ```bash theme={null}
        oci bv boot-volume get \
          --boot-volume-id <BOOT_VOLUME_OCID> \
          --query 'data."kms-key-id"' \
          --raw-output
        ```

        If it returns your `<KEY_OCID>`, the boot volume is now encrypted with a customer-managed key.

        ***

        This sequence (create/identify CMK → grant Block Storage access → update boot-volume `kms-key-id`) is what remediates the “OCI Storage Boot Volumes Should Be Encrypted With Customer-Managed Keys” finding using OCI CLI.
      </Accordion>

      <Accordion title="Using Python">
        Below is a step‑by‑step approach and example Python code to:

        1. **Monitor** OCI boot volumes for non‑compliance (not using customer-managed keys).
        2. **Remediate** by updating the boot volume to use a customer-managed KMS key (where supported).

        ***

        ## 1. Prerequisites

        1. **OCI CLI config** set up on the machine where you’ll run Python:
           * `~/.oci/config` with a profile that has:
             * `tenancy`
             * `user`
             * `fingerprint`
             * `key_file`
             * `region`

        2. **Permissions** for the principal used by the SDK:
           * To manage block volumes and KMS keys:
             ```text theme={null}
             allow group SecOps to manage volume-family in tenancy
             allow group SecOps to use keys in tenancy
             allow service blockstorage to use keys in tenancy
             ```
           * Adjust `SecOps` to your group and scoping as needed.

        3. **Customer‑Managed KMS Key** already created in OCI Vault:
           * Get the **OCID of the key**: `kms_key_id = "ocid1.key.oc1...."`
           * Ensure the key is in the **same region** as your boot volumes.

        ***

        ## 2. High-Level Steps

        1. Identify **compartments** you want to monitor.
        2. For each compartment:
           * List **boot volumes**.
           * Check each boot volume’s `kms_key_id`.
        3. **Monitoring**:
           * Log/report volumes where `kms_key_id` is `None` or not equal to your required key.
        4. **Remediation**:
           * Call `UpdateBootVolume` with `kms_key_id` set to your customer-managed key.
           * Optionally, tag or log what was changed.

        ***

        ## 3. Python Example: Monitor & Remediate Boot Volume Encryption

        Install SDK (if not already):

        ```bash theme={null}
        pip install oci
        ```

        ### 3.1. Configuration

        Adjust these values in the code:

        * `PROFILE_NAME` – OCI CLI profile to use.
        * `TARGET_COMPARTMENT_IDS` – list of compartment OCIDs to scan, or use the tenancy and list all.
        * `REQUIRED_KMS_KEY_ID` – OCID of your **customer-managed key**.

        ### 3.2. Script

        ```python theme={null}
        import oci
        from oci.core import BlockstorageClient
        from oci.identity import IdentityClient

        # ---------------- CONFIG ----------------
        PROFILE_NAME = "DEFAULT"  # OCI CLI profile
        REQUIRED_KMS_KEY_ID = "ocid1.key.oc1..xxxxxxxx"  # Your customer-managed KMS key
        TARGET_COMPARTMENT_IDS = []  # Optional: fill with compartment OCIDs; if empty, use all under tenancy
        DRY_RUN = True  # Set to False to actually remediate
        # ----------------------------------------


        def get_config(profile_name):
            return oci.config.from_file("~/.oci/config", profile_name=profile_name)


        def list_all_compartments(identity_client, tenancy_id):
            """Return list of active compartments under a tenancy (flattened)."""
            compartments = []

            def _list_children(parent_id):
                response = oci.pagination.list_call_get_all_results(
                    identity_client.list_compartments,
                    tenancy_id,
                    compartment_id_in_subtree=True,
                    access_level="ACCESSIBLE",
                )
                for c in response.data:
                    if c.lifecycle_state == "ACTIVE":
                        compartments.append(c)

            _list_children(tenancy_id)
            return compartments


        def list_boot_volumes(bs_client, compartment_id, availability_domains):
            """List all boot volumes in a compartment across all ADs."""
            boot_volumes = []
            for ad in availability_domains:
                response = oci.pagination.list_call_get_all_results(
                    bs_client.list_boot_volumes,
                    compartment_id=compartment_id,
                    availability_domain=ad.name,
                )
                boot_volumes.extend(response.data)
            return boot_volumes


        def main():
            config = get_config(PROFILE_NAME)
            tenancy_id = config["tenancy"]

            identity_client = IdentityClient(config)
            bs_client = BlockstorageClient(config)

            # Get availability domains for the region
            ads = identity_client.list_availability_domains(tenancy_id).data

            # Determine compartments to scan
            if TARGET_COMPARTMENT_IDS:
                compartments_to_scan = TARGET_COMPARTMENT_IDS
            else:
                all_compartments = list_all_compartments(identity_client, tenancy_id)
                compartments_to_scan = [c.id for c in all_compartments] + [tenancy_id]

            print(f"Scanning {len(compartments_to_scan)} compartments...")

            non_compliant = []
            updated = []

            for compartment_id in compartments_to_scan:
                boot_vols = list_boot_volumes(bs_client, compartment_id, ads)

                for bv in boot_vols:
                    current_kms_key = getattr(bv, "kms_key_id", None)

                    # Check compliance: must be encrypted with REQUIRED_KMS_KEY_ID
                    if not current_kms_key:
                        status = "UNENCRYPTED (no KMS key)"
                        compliant = False
                    elif current_kms_key != REQUIRED_KMS_KEY_ID:
                        status = f"ENCRYPTED with different KMS key: {current_kms_key}"
                        compliant = False
                    else:
                        status = "COMPLIANT"
                        compliant = True

                    print(f"[{status}] BootVolume: {bv.display_name} ({bv.id}) in compartment {compartment_id}")

                    if not compliant:
                        non_compliant.append(bv.id)

                        # Remediation: update the boot volume to use REQUIRED_KMS_KEY_ID
                        if not DRY_RUN:
                            try:
                                update_details = oci.core.models.UpdateBootVolumeDetails(
                                    kms_key_id=REQUIRED_KMS_KEY_ID
                                )
                                response = bs_client.update_boot_volume(bv.id, update_details)
                                updated.append(response.data.id)
                                print(f"  -> Remediated: set kms_key_id={REQUIRED_KMS_KEY_ID}")
                            except Exception as e:
                                print(f"  -> ERROR updating boot volume {bv.id}: {e}")

            print("\n=== SUMMARY ===")
            print(f"Non-compliant boot volumes found: {len(non_compliant)}")
            print(f"Remediated (this run): {len(updated)}")
            if DRY_RUN:
                print("NOTE: DRY_RUN is True; no changes were applied.")


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

        ***

        ## 4. How to Use for “Monitoring” Only

        1. Keep `DRY_RUN = True`.
        2. Run on a schedule (e.g., cron or CI pipeline).
        3. Redirect output to logs or integrate with your logging/alerting:
           * Parse the `Non-compliant boot volumes found` count.
           * Trigger alerts when > 0.

        ***

        ## 5. To Enable Automatic Remediation

        1. Set `DRY_RUN = False`.
        2. Ensure IAM policies allow:
           * `update` on boot volumes.
           * `use` on the KMS key.
        3. Optionally:
           * Add tagging in `UpdateBootVolumeDetails` to mark remediated resources.

        If you share your compartment structure or how you prefer alerts delivered (email, OCI Monitoring metrics, etc.), I can adapt the script to push metrics or alarms specifically for “OCI Storage Monitoring.”
      </Accordion>

      <Accordion title="Using Terraform">
        ```hcl theme={null}
        # Customer-managed KMS vault (if not already created)
        resource "oci_kms_vault" "CMK_VAULT" {
          compartment_id = "OCID_OF_COMPARTMENT_FOR_KMS_VAULT"
          display_name   = "CMK_VAULT_NAME"
          vault_type     = "DEFAULT" # or "VIRTUAL_PRIVATE"
        }

        # Master encryption key (Customer-Managed Key / CMK)
        resource "oci_kms_key" "BOOT_VOLUME_CMK" {
          compartment_id = "OCID_OF_COMPARTMENT_FOR_KMS_KEY"
          display_name   = "BOOT_VOLUME_CMK_NAME"
          key_shape {
            algorithm = "AES"
            length    = 32
          }
          management_endpoint = oci_kms_vault.CMK_VAULT.management_endpoint
        }

        # Boot volume encrypted with the CMK
        resource "oci_core_boot_volume" "ENCRYPTED_BOOT_VOLUME" {
          availability_domain = "AVAILABILITY_DOMAIN_NAME"
          compartment_id      = "OCID_OF_BOOT_VOLUME_COMPARTMENT"

          # If cloning from an existing boot volume or backup, set source_details here
          # source_details {
          #   type                = "bootVolume"
          #   id                  = "OCID_OF_SOURCE_BOOT_VOLUME_OR_BACKUP"
          # }

          kms_key_id = oci_kms_key.BOOT_VOLUME_CMK.id  # Enforce CMK-based encryption
          size_in_gbs = 50                             # ADJUST_SIZE_IN_GB
          display_name = "ENCRYPTED_BOOT_VOLUME_NAME"
        }
        ```

        Substitute:

        * `OCID_OF_COMPARTMENT_FOR_KMS_VAULT` with the OCID of the compartment where the vault should live.
        * `OCID_OF_COMPARTMENT_FOR_KMS_KEY` with the OCID of the compartment for the key.
        * `AVAILABILITY_DOMAIN_NAME` with the target availability domain (e.g., `"kIdk:PHX-AD-1"`).
        * `OCID_OF_BOOT_VOLUME_COMPARTMENT` with the boot volume’s compartment OCID.
        * Optional `source_details.id` with the OCID of the existing boot volume or backup you want to base this on.

        Changing or adding `kms_key_id` on an existing `oci_core_boot_volume` typically forces replacement of the boot volume; this can cause an outage and data loss if you don’t coordinate creating/attaching a new boot volume and updating any instances that use it.

        Verification with `terraform plan` should show the boot volume either:

        * being newly created with `kms_key_id = oci_kms_key.BOOT_VOLUME_CMK.id`, or
        * being replaced with the new resource having that `kms_key_id` argument set.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
