> ## 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 Block Volumes Should Be Encrypted With Customer-Managed Keys

### More Info:

Block volumes should be encrypted using Customer-Managed Keys (CMKs). Managing your own keys provides a higher level of data security and cryptographic isolation compared to default Oracle-managed keys

### 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">
        Below are the concise step‑by‑step actions in the OCI Console to ensure **Block Volumes are encrypted with customer‑managed keys (CMK)** rather than Oracle‑managed keys.

        ***

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

        1. Sign in to the **OCI Console**.
        2. Open the navigation menu → **Identity & Security** → **Vault**.
        3. Choose the **Compartment** where you want the vault.
        4. Click **Create vault** (if you don’t already have one):
           * Type: typically **Default** (or **Virtual Private** depending on your needs).
           * Compartment: select the appropriate one.
           * Click **Create vault**.
        5. After the vault is in **Active** state, click into the vault.
        6. Go to **Master Encryption Keys** (or **Keys**).
        7. Click **Create key**:
           * Key type: **AES** (for block volumes).
           * Protection mode: **HSM** or **Software** as per your policy.
           * Set name/description and click **Create key**.
        8. Note the **OCID** and **name** of the created key.

        ***

        ## 2. Use CMK for New Block Volumes

        When you create new Block Volumes, explicitly select the CMK:

        1. Navigation menu → **Storage** → **Block Volumes**.
        2. Click **Create block volume**.
        3. Set:
           * **Compartment**, **Availability Domain**, **Size**, etc.
        4. Under **Encryption**:
           * Choose **Customer-managed keys** (or **Encrypt using a key that you manage**).
           * Select your **Vault** and then your **Key** from the drop‑down.
        5. Click **Create block volume**.

        All new volumes created with that setting are encrypted with your CMK.

        ***

        ## 3. Remediate Existing Block Volumes (Re-encrypt with CMK)

        Block Volumes cannot have the encryption key changed in-place. You must create a *new* volume encrypted with your CMK from a backup of the existing one.

        For each existing volume currently using Oracle-managed keys:

        ### 3.1 Create a Backup of the Existing Volume

        1. Navigation menu → **Storage** → **Block Volumes**.
        2. Select the **Block Volume** to remediate.
        3. From the **More actions** or **Actions** menu, choose **Create backup**.
        4. Provide:
           * **Backup name**.
           * **Backup type**: usually **Full backup**.
        5. Click **Create backup** and wait until the backup is **Available**.

        ### 3.2 Create a New CMK-Encrypted Volume from the Backup

        1. Go to **Block Volume Backups** (from the same Block Volumes page or left-side link).
        2. Click the backup you just created.
        3. Click **Create block volume** from this backup.
        4. Configure:
           * **Compartment**, **Availability Domain** as required.
        5. Under **Encryption**:
           * Select **Customer-managed keys**.
           * Choose your **Vault** and **CMK**.
        6. Click **Create block volume**.

        You now have a new volume, same data, but encrypted with the CMK.

        ### 3.3 Swap the Old Volume with the New One

        For each attached volume:

        1. Identify the **instance(s)** where the old volume is attached:
           * Navigation menu → **Compute** → **Instances** → click the instance → **Attached block volumes**.
        2. Gracefully **stop** or **quiesce** the application/OS if needed (data‑consistency decision).
        3. **Detach** the old volume:
           * On the instance details page, next to the old volume, click **Detach**.
        4. **Attach** the new CMK-encrypted volume:
           * Click **Attach block volume**.
           * Choose the new volume.
           * Set attachment type (iSCSI or paravirtualized) same as previous.
           * Complete the attach.
        5. On the instance (OS level), ensure:
           * The new device is recognized.
           * Mount it to the same mount point or update fstab as needed.
        6. Validate data and application functionality.
        7. After verification, **delete** the old volume (if no longer needed) to avoid extra cost and reduce risk.

        ***

        ## 4. Set CMK as Default for Future Block Volume Creation (Optional)

        If your tenancy policy allows, you can enforce or standardize CMK usage:

        1. Use **Tagging** or **Compartment policies** operationally so all block volumes in a given compartment are created with the CMK.
        2. For operational enforcement/monitoring, you can:
           * Use **Cloud Guard** (Security → Cloud Guard) to:
             * Enable a target (tenancy/compartment).
             * Enable detectors for storage/compute and configure **Responder Recipes** to alert on volumes not using CMK.

        ***

        ## 5. Monitoring (Verifying Compliance in OCI Console)

        To continuously monitor that Block Volumes use CMKs:

        1. Navigation menu → **Observability & Management** → **Cloud Guard**.
        2. Ensure **Cloud Guard** is **Enabled** with a target covering your compartments.
        3. Edit the **Detector Recipe**:
           * Look for detectors relating to **block storage encryption** or **Oracle-managed vs customer-managed keys** (names can differ by region/version).
           * Ensure they are **Enabled**.
        4. Configure **Responder Recipe** to:
           * At least send **notifications** (via Notifications service → topics and subscriptions).
        5. Check **Cloud Guard → Findings** regularly or feed into SIEM for continuous monitoring.

        ***

        If you share whether you want to remediate at scale (many volumes/compartments), I can add a very short OCI CLI/script approach as well.
      </Accordion>

      <Accordion title="Using CLI">
        Below are concise, step‑by‑step OCI CLI instructions to ensure Block Volumes are encrypted with customer‑managed keys (CMK).

        Assumptions:

        * You already have OCI CLI configured (`oci setup config`) with proper permissions.
        * Replace all placeholder values (`<...>`) with your real OCIDs / names.

        ***

        ## 1. Create a Vault (if you don’t already have one)

        ```bash theme={null}
        # 1.1 Create a Vault
        oci kms management vault create \
          --compartment-id <COMPARTMENT_OCID> \
          --display-name "cmk-vault" \
          --vault-type DEFAULT \
          --wait-for-state ACTIVE

        # 1.2 Capture the Vault OCID from the output:
        # "id": "ocid1.vault.oc1..xxxxx"
        VAULT_OCID=<VAULT_OCID>
        ```

        ***

        ## 2. Create a Key inside the Vault

        ```bash theme={null}
        # 2.1 Create a Master Encryption Key (CMK)
        oci kms management key create \
          --compartment-id <COMPARTMENT_OCID> \
          --display-name "block-volume-cmk" \
          --vault-id $VAULT_OCID \
          --key-shape '{"algorithm": "AES", "length": 32}' \
          --protection-mode SOFTWARE \
          --wait-for-state ENABLED

        # 2.2 Capture the Key OCID:
        # "id": "ocid1.key.oc1..xxxxx"
        KMS_KEY_OCID=<KEY_OCID>
        ```

        ***

        ## 3. Use CMK for New Block Volumes

        When creating block volumes, specify `--kms-key-id`:

        ```bash theme={null}
        oci bv volume create \
          --availability-domain "<AD_NAME>" \
          --compartment-id <COMPARTMENT_OCID> \
          --display-name "my-encrypted-volume" \
          --size-in-gbs 100 \
          --kms-key-id $KMS_KEY_OCID \
          --wait-for-state AVAILABLE
        ```

        For boot volumes (when launching a compute instance):

        ```bash theme={null}
        oci compute instance launch \
          --compartment-id <COMPARTMENT_OCID> \
          --availability-domain "<AD_NAME>" \
          --shape "<SHAPE_NAME>" \
          --subnet-id <SUBNET_OCID> \
          --image-id <IMAGE_OCID> \
          --metadata '{"ssh_authorized_keys": "<YOUR_SSH_KEY>"}' \
          --block-volumes '{"sourceDetails": {"type": "image", "imageId": "<IMAGE_OCID>"}, "kmsKeyId": "'"$KMS_KEY_OCID"'"}'
        ```

        (Or use `--launch-options` / `--block-volume-details` JSON as appropriate for your environment.)

        ***

        ## 4. Migrate Existing Volumes to CMK

        ### 4.1 List existing Block Volumes

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

        Check each volume’s encryption key:

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

        If returned value is empty or not your CMK, update it.

        ### 4.2 Re-encrypt an existing Block Volume with CMK

        ```bash theme={null}
        oci bv volume update \
          --volume-id <VOLUME_OCID> \
          --kms-key-id $KMS_KEY_OCID \
          --force \
          --wait-for-state AVAILABLE
        ```

        Repeat for all non‑compliant volumes.

        > If attached to running instances, ensure you update in a scheduled maintenance window in case of performance impact during re-encryption.

        ***

        ## 5. (Optional) Set Policy So All New Volumes Use CMK by Default

        OCI doesn’t currently support a tenancy‑wide “default CMK” for block volumes solely by config; enforcement is usually done via:

        * **Cloud Guard** / **Security Zones** to detect non‑CMK volumes.
        * **Golden images / Terraform / scripts** that always pass `--kms-key-id`.

        For CLI‑driven provisioning, standardize scripts to always include `--kms-key-id $KMS_KEY_OCID`.

        ***

        ## 6. Hook into “Storage Monitoring” / Compliance

        To make sure your “OCI Storage Monitoring” (Cloud Guard / custom monitoring) shows compliance:

        * Ensure all block volumes have a non‑empty `kms-key-id` and that it equals your CMK OCID.
        * You can script a compliance check:

        ```bash theme={null}
        oci bv volume list \
          --compartment-id <COMPARTMENT_OCID> \
          --all \
          --query "data[?\"kms-key-id\"==''].{\"name\": \"display-name\", id: id}" \
          --output table
        ```

        Any row returned is non‑compliant (not using CMK). Then remediate with the `volume update` command above.

        If you tell me which monitoring tool you're using (Cloud Guard, custom scripts, etc.), I can give you an exact check/remediation script end-to-end.
      </Accordion>

      <Accordion title="Using Python">
        Below is how to remediate this in OCI and then monitor it using Python.

        ***

        ## 1. What “remediation” means for OCI Block Volumes

        In OCI:

        * A block volume is either:
          * Encrypted with **Oracle-managed keys** (default), or
          * Encrypted with a **customer-managed key (CMK)** from OCI Vault.

        You cannot just “flip” an existing volume’s key. To remediate:

        1. Ensure a **Vault** and **Key** exist.
        2. Ensure **all future volumes** are created with that CMK.
        3. For existing volumes, **migrate** to new volumes encrypted with CMK (backup → restore with CMK).
        4. Implement **monitoring** to detect any volume not using CMK.

        The user asked specifically “using Python” for OCI Storage Monitoring, so the script below focuses on:

        * Detecting non‑compliant volumes (not using CMK).
        * Optionally guiding migration steps.

        ***

        ## 2. Preconditions

        Before running the Python script:

        1. Install SDK:
           ```bash theme={null}
           pip install oci
           ```

        2. Configure OCI CLI/SDK credentials (user, tenancy, region, key):
           * Typically `~/.oci/config` with a profile, e.g. `[DEFAULT]`.

        3. Have a **Vault** and **Customer-Managed Key**:
           * Vault type: Virtual Private or Default (up to you).
           * Record the Key OCID: `ocid1.key.oc1...`

        ***

        ## 3. Python: Monitor Block Volumes for CMK Usage

        This script:

        * Iterates through all compartments and block volumes in a tenancy.
        * Checks `kms_key_id` on each volume.
        * Flags volumes not encrypted with CMK (i.e., using Oracle-managed keys).
        * (Optional) Can be narrowed to a single compartment or region.

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

        # ------------- CONFIG -------------
        PROFILE = "DEFAULT"     # OCI config profile name
        CONFIG_FILE = "~/.oci/config"
        TARGET_REGION = None    # e.g. "us-ashburn-1", or None for region in config
        # If you want to check against specific CMKs:
        ALLOWED_KEY_OCIDS = []  # e.g. ["ocid1.key.oc1..xxxxx"]
        # ---------------------------------


        def get_all_compartments(identity_client, tenancy_id):
            compartments = []
            list_compartments_response = oci.pagination.list_call_get_all_results(
                identity_client.list_compartments,
                tenancy_id,
                compartment_id_in_subtree=True,
                access_level="ANY"
            )
            compartments.extend(list_compartments_response.data)
            # Include root compartment itself
            root = identity_client.get_compartment(tenancy_id).data
            compartments.append(root)
            return compartments


        def main():
            config = oci.config.from_file(CONFIG_FILE, PROFILE)

            if TARGET_REGION:
                config["region"] = TARGET_REGION

            identity_client = IdentityClient(config)
            block_client = BlockstorageClient(config)

            tenancy_id = config["tenancy"]

            print("Scanning compartments and block volumes...")

            compartments = get_all_compartments(identity_client, tenancy_id)

            non_compliant_volumes = []

            for compartment in compartments:
                if compartment.lifecycle_state != "ACTIVE":
                    continue

                comp_id = compartment.id
                comp_name = compartment.name

                # List block volumes in the compartment
                volumes = oci.pagination.list_call_get_all_results(
                    block_client.list_volumes,
                    compartment_id=comp_id
                ).data

                for vol in volumes:
                    # kms_key_id is None or empty => Oracle-managed key
                    # If ALLOWED_KEY_OCIDS is provided, enforce those
                    kms_key_id = vol.kms_key_id

                    uses_cmk = False
                    if kms_key_id:
                        if ALLOWED_KEY_OCIDS:
                            uses_cmk = (kms_key_id in ALLOWED_KEY_OCIDS)
                        else:
                            # Any non-empty kms_key_id is treated as "customer-managed" for monitoring
                            uses_cmk = True

                    if not uses_cmk:
                        non_compliant_volumes.append((comp_name, vol))

            print("\n=== Non-compliant Block Volumes (not using CMK) ===")
            if not non_compliant_volumes:
                print("All block volumes are using customer-managed keys (or meet the allowed-key policy).")
            else:
                for comp_name, vol in non_compliant_volumes:
                    print(f"Compartment: {comp_name}")
                    print(f"  Volume OCID: {vol.id}")
                    print(f"  Display Name: {vol.display_name}")
                    print(f"  Size (GB): {vol.size_in_gbs}")
                    print(f"  KMS Key ID: {vol.kms_key_id}")
                    print("  STATUS: NON-COMPLIANT (Oracle-managed key)\n")


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

        You can run this periodically (e.g., via cron, OCI Functions, or OCI Cloud Shell + scheduler) and send the output to:

        * Logging / SIEM
        * Email / notification (using OCI Notifications)

        ***

        ## 4. Enforcing CMK for New Volumes (Python Example)

        When you create volumes, always pass `kms_key_id`:

        ```python theme={null}
        import oci
        from oci.core import BlockstorageClient
        from oci.core.models import CreateVolumeDetails

        config = oci.config.from_file("~/.oci/config", "DEFAULT")
        block_client = BlockstorageClient(config)

        compartment_id = "<compartment_ocid>"
        availability_domain = "<AD-name>"  # e.g. "kIdk:US-ASHBURN-AD-1"
        kms_key_id = "<ocid1.key.oc1..your_cmk_ocid>"

        create_volume_details = CreateVolumeDetails(
            compartment_id=compartment_id,
            availability_domain=availability_domain,
            size_in_gbs=50,
            display_name="cmk-encrypted-volume",
            kms_key_id=kms_key_id
        )

        response = block_client.create_volume(create_volume_details)
        print("Created volume:", response.data.id)
        ```

        ***

        ## 5. Migrating Existing Non‑Compliant Volumes to CMK

        You must:

        1. **Create a backup** of the existing (Oracle-managed) volume.
        2. **Restore** a new volume from that backup, specifying `kms_key_id` for the CMK.
        3. **Detach** old volume from instance, **attach** new CMK-encrypted volume.
        4. Decommission the old volume once data is validated.

        Python outline (simplified):

        ```python theme={null}
        from oci.core.models import CreateVolumeBackupDetails, CreateVolumeDetails

        volume_id = "<non_compliant_volume_ocid>"
        compartment_id = "<compartment_ocid>"
        kms_key_id = "<cmk_ocid>"

        # 1. Create backup
        backup_details = CreateVolumeBackupDetails(
            volume_id=volume_id,
            display_name="temp-backup-for-cmk-migration"
        )
        backup = block_client.create_volume_backup(backup_details).data

        # Wait for backup to be available (polling omitted for brevity)

        # 2. Restore new volume from backup with CMK
        create_from_backup = CreateVolumeDetails(
            compartment_id=compartment_id,
            availability_domain="<AD-name>",
            display_name="cmk-encrypted-restored-volume",
            source_details={"type": "volumeBackup", "id": backup.id},
            kms_key_id=kms_key_id
        )
        new_volume = block_client.create_volume(create_from_backup).data

        print("New CMK-encrypted volume OCID:", new_volume.id)
        ```

        (Attach/detach operations depend on your compute setup and can be automated with `oci.core.ComputeClient`.)

        ***

        If you tell me how you want to run this (OCI Functions, local cron, etc.) I can adapt the monitoring code to emit logs or metrics in that environment.
      </Accordion>

      <Accordion title="Using Terraform">
        ```hcl theme={null}
        # Customer-managed key (CMK) in OCI Vault
        resource "oci_kms_key" "BLOCK_VOLUME_CMK" {
          # Substitute with your KMS management endpoint (e.g. from oci_kms_vault.vault.management_endpoint)
          management_endpoint = "KMS_MANAGEMENT_ENDPOINT"

          compartment_id = "COMPARTMENT_OCID"

          display_name = "BLOCK_VOLUME_CMK_NAME"
          key_shape {
            algorithm = "AES"
            length    = 32
          }
          protection_mode = "HSM" # or "SOFTWARE" as per your requirement
        }

        # Block volume encrypted with customer-managed key
        resource "oci_core_volume" "BLOCK_VOLUME" {
          availability_domain = "AVAILABILITY_DOMAIN_NAME"
          compartment_id      = "COMPARTMENT_OCID"
          display_name        = "BLOCK_VOLUME_NAME"
          size_in_gbs         = 50

          # Critical: use CMK for encryption instead of default Oracle-managed key
          kms_key_id = oci_kms_key.BLOCK_VOLUME_CMK.id

          # Add any other arguments you already use (backup_policy_id, volume_group_id, etc.)
        }
        ```

        Changing `kms_key_id` on an existing `oci_core_volume` forces replacement of the volume; applying this to an in-use volume will destroy and recreate it, so you must plan migration or restore from backup accordingly.

        For verification, `terraform plan` should show `kms_key_id` set to the CMK ID on the volume and that the `oci_core_volume.BLOCK_VOLUME` resource will be replaced (destroyed and created) to apply the new encryption.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
