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

# Use BYOK for Disk Volumes Encryption

### More Info:

Ensure that your Azure virtual machine disk volumes are using customer-managed keys (also known as Bring Your Own Keys - BYOKs) instead of service-managed keys (default keys used by Microsoft Azure for disk encryption), in order to have a more granular control over your VM data encryption/decryption process.

### Risk Level

High

### Address

Security

### Compliance Standards

* HITRUST CSF
* NIST CSF
* PCI
* SOC2
* Securities and Exchange Board of India (SEBI) - Cloud Security Adoption Framework

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Using Console" defaultOpen="true">
        To remediate the misconfiguration of not using BYOK for disk volume encryption in Azure, follow these steps:

        1. Log in to the Azure portal ([https://portal.azure.com/](https://portal.azure.com/)).
        2. Navigate to the "Key Vaults" menu and create a new Key Vault if you do not have an existing one.
        3. In the "Key Vaults" menu, select the Key Vault that you want to use for BYOK.
        4. In the Key Vault, select the "Keys" menu and create a new key.
        5. Provide a name for the key, select "RSA" as the key type, and provide a key size of at least 2048 bits.
        6. Select the "BYOK" option under "Key Options" and provide the URI of your on-premises key management service (KMS).
        7. Save the key and take note of the key identifier (URI) for later use.
        8. Navigate to the "Disks" menu and select the disk that you want to encrypt using BYOK.
        9. Under the "Encryption" tab, select "Disk encryption set" and click "Create new".
        10. Provide a name for the disk encryption set and select the Key Vault that you created in step 2.
        11. In the "Key management" section, select "Bring your own key (BYOK)" and provide the key identifier (URI) that you noted in step 7.
        12. Save the disk encryption set and wait for the encryption process to complete.

        By following these steps, you have successfully remediated the misconfiguration by using BYOK for disk volume encryption in Azure.

        #
      </Accordion>

      <Accordion title="Using CLI">
        To remediate the misconfiguration of not using Bring Your Own Key (BYOK) for Disk Volumes Encryption on Azure using Azure CLI, follow the below steps:

        1. Create a new Key Vault in Azure or use an existing one.

        2. Create a new Key in the Key Vault or use an existing one.

        3. Grant the Disk Encryption Set (DES) access to the Key Vault and Key.

        4. Enable disk encryption using the Key Vault and Key.

        The following are the detailed steps to remediate the misconfiguration:

        Step 1: Create a new Key Vault in Azure or use an existing one

        Use the below command to create a new Key Vault in Azure:

        ```
        az keyvault create --name "key-vault-name" --resource-group "resource-group-name" --location "location"
        ```

        Replace "key-vault-name" with the name of the Key Vault, "resource-group-name" with the name of the resource group, and "location" with the location of the Key Vault.

        Step 2: Create a new Key in the Key Vault or use an existing one

        Use the below command to create a new Key in the Key Vault:

        ```
        az keyvault key create --vault-name "key-vault-name" --name "key-name" --protection software --size 2048
        ```

        Replace "key-vault-name" with the name of the Key Vault and "key-name" with the name of the Key.

        Step 3: Grant the Disk Encryption Set (DES) access to the Key Vault and Key

        Use the below command to grant the Disk Encryption Set (DES) access to the Key Vault:

        ```
        az keyvault set-policy --name "key-vault-name" --object-id "object-id" --key-permissions "wrapkey" --secret-permissions "set"
        ```

        Replace "key-vault-name" with the name of the Key Vault and "object-id" with the object ID of the Disk Encryption Set (DES).

        Use the below command to grant the Disk Encryption Set (DES) access to the Key:

        ```
        az keyvault set-policy --name "key-vault-name" --object-id "object-id" --key-permissions "get" --secret-permissions "get"
        ```

        Replace "key-vault-name" with the name of the Key Vault and "object-id" with the object ID of the Disk Encryption Set (DES).

        Step 4: Enable disk encryption using the Key Vault and Key

        Use the below command to enable disk encryption using the Key Vault and Key:

        ```
        az disk encryption set update --resource-group "resource-group-name" --name "disk-encryption-set-name" --key-url "key-url" --key-vault-id "key-vault-id"
        ```

        Replace "resource-group-name" with the name of the resource group, "disk-encryption-set-name" with the name of the Disk Encryption Set (DES), "key-url" with the URL of the Key, and "key-vault-id" with the ID of the Key Vault.

        After following these steps, the misconfiguration of not using BYOK for Disk Volumes Encryption on Azure using Azure CLI will be remediated.
      </Accordion>

      <Accordion title="Using Python">
        To remediate the misconfiguration of not using BYOK for Disk Volumes Encryption in AZURE using Python, follow the steps below:

        1. First, you need to create a new key vault in Azure. To create a key vault, you can use the `azure-mgmt-keyvault` Python package. Install the package using the following command:

           ```
           pip install azure-mgmt-keyvault
           ```

           Then, use the following code snippet to create a new key vault:

           ```python theme={null}
           from azure.identity import DefaultAzureCredential
           from azure.mgmt.keyvault import KeyVaultManagementClient
           from azure.mgmt.keyvault.models import VaultCreateOrUpdateParameters, Sku, AccessPolicyEntry, Permissions, SecretPermissions

           # Set the subscription ID and resource group name
           subscription_id = '<your-subscription-id>'
           resource_group_name = '<your-resource-group-name>'

           # Set the key vault name and region
           vault_name = '<your-key-vault-name>'
           region = '<your-region>'

           # Create the key vault management client
           credential = DefaultAzureCredential()
           keyvault_client = KeyVaultManagementClient(credential, subscription_id)

           # Set the SKU and access policies for the key vault
           sku = Sku(name='standard', family='A')
           access_policy = AccessPolicyEntry(
               tenant_id='<your-tenant-id>',
               object_id='<your-object-id>',
               permissions=Permissions(
                   secrets=[SecretPermissions.get, SecretPermissions.list, SecretPermissions.set]
               )
           )

           # Create the key vault parameters
           parameters = VaultCreateOrUpdateParameters(
               location=region,
               properties={
                   'sku': sku,
                   'access_policies': [access_policy]
               }
           )

           # Create the key vault
           keyvault_client.vaults.create_or_update(resource_group_name, vault_name, parameters)
           ```

        2. Next, you need to create a new key in the key vault. To create a new key, you can use the `azure-keyvault-keys` Python package. Install the package using the following command:

           ```
           pip install azure-keyvault-keys
           ```

           Then, use the following code snippet to create a new key:

           ```python theme={null}
           from azure.identity import DefaultAzureCredential
           from azure.keyvault.keys import KeyClient
           from azure.keyvault.keys.crypto import CryptographyClient, EncryptionAlgorithm

           # Set the key vault URL and key name
           key_vault_url = f'https://{vault_name}.vault.azure.net/'
           key_name = '<your-key-name>'

           # Create the key client and cryptography client
           credential = DefaultAzureCredential()
           key_client = KeyClient(key_vault_url, credential)
           crypto_client = CryptographyClient(key_client.get_key(key_name).id, credential)

           # Generate a new RSA key pair
           key_size = 2048
           key_ops = ['encrypt', 'decrypt']
           key = key_client.create_rsa_key(name=key_name, size=key_size, key_operations=key_ops)

           # Encrypt a test message using the new key
           message = b'This is a test message.'
           encrypted_message = crypto_client.encrypt(EncryptionAlgorithm.rsa_oaep, message)
           ```

        3. Finally, you need to enable BYOK for disk volume encryption in Azure. To do this, you can use the `azure-mgmt-compute` Python package. Install the package using the following command:

           ```
           pip install azure-mgmt-compute
           ```

           Then, use the following code snippet to enable BYOK for disk volume encryption:

           ```python theme={null}
           from azure.identity import DefaultAzureCredential
           from azure.mgmt.compute import ComputeManagementClient
           from azure.mgmt.compute.models import DiskEncryptionSetParameters, EncryptionSetIdentity

           # Set the subscription ID and resource group name
           subscription_id = '<your-subscription-id>'
           resource_group_name = '<your-resource-group-name>'

           # Set the disk encryption set name and key vault URL
           disk_encryption_set_name = '<your-disk-encryption-set-name>'
           key_vault_url = f'https://{vault_name}.vault.azure.net/'

           # Create the compute management client
           credential = DefaultAzureCredential()
           compute_client = ComputeManagementClient(credential, subscription_id)

           # Create the disk encryption set parameters
           identity = EncryptionSetIdentity(type='UserAssigned', user_assigned_identities={
               f'/subscriptions/{subscription_id}/resourceGroups/{resource_group_name}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/{key_name}': {}
           })
           parameters = DiskEncryptionSetParameters(
               identity=identity,
               key_vault_uri=key_vault_url
           )

           # Create the disk encryption set
           compute_client.disk_encryption_sets.create_or_update(resource_group_name, disk_encryption_set_name, parameters)
           ```

           Note that you need to replace the placeholders `<your-subscription-id>`, `<your-resource-group-name>`, `<your-key-vault-name>`, `<your-region>`, `<your-tenant-id>`, `<your-object-id>`, `<your-key-name>`, `<your-disk-encryption-set-name>` with your own values.
      </Accordion>

      <Accordion title="Using Terraform">
        ```hcl theme={null}
        # Customer-managed key in Key Vault
        resource "azurerm_key_vault" "DISK_KV" {
          name                        = "DISK_KV_NAME"          # replace with your Key Vault name
          resource_group_name         = "RESOURCE_GROUP_NAME"   # replace
          location                    = "AZURE_REGION"          # replace
          tenant_id                   = "TENANT_ID"             # replace
          sku_name                    = "standard"
          purge_protection_enabled    = true
          soft_delete_retention_days  = 90

          # Ensure the Disk Encryption Set (and deployer) principals get key permissions
        }

        resource "azurerm_key_vault_key" "DISK_CMK" {
          name         = "DISK_CMK_NAME"        # replace
          key_vault_id = azurerm_key_vault.DISK_KV.id
          key_type     = "RSA"
          key_size     = 2048

          key_opts = [
            "decrypt",
            "encrypt",
            "wrapKey",
            "unwrapKey",
          ]
        }

        # Disk Encryption Set that points at the CMK
        resource "azurerm_disk_encryption_set" "DISK_DES" {
          name                = "DISK_DES_NAME"             # replace
          resource_group_name = "RESOURCE_GROUP_NAME"       # replace
          location            = "AZURE_REGION"              # replace

          key_vault_key_id = azurerm_key_vault_key.DISK_CMK.id

          identity {
            type = "SystemAssigned"
          }
        }

        # Allow the Disk Encryption Set's managed identity to use the key
        resource "azurerm_key_vault_access_policy" "DES_POLICY" {
          key_vault_id = azurerm_key_vault.DISK_KV.id
          tenant_id    = "TENANT_ID"                                # replace
          object_id    = azurerm_disk_encryption_set.DISK_DES.identity[0].principal_id

          key_permissions = [
            "get",
            "wrapKey",
            "unwrapKey",
          ]
        }

        # Linux/Windows VM using BYOK for OS and data disks
        resource "azurerm_linux_virtual_machine" "VM" {
          name                = "VM_NAME"                 # replace
          resource_group_name = "RESOURCE_GROUP_NAME"     # replace
          location            = "AZURE_REGION"            # replace
          size                = "Standard_DS1_v2"         # replace
          admin_username      = "ADMIN_USERNAME"          # replace
          network_interface_ids = [
            "NIC_RESOURCE_ID",                            # replace with azurerm_network_interface.<NAME>.id
          ]

          admin_ssh_key {
            username   = "ADMIN_USERNAME"                # same as above
            public_key = "SSH_PUBLIC_KEY_CONTENT"        # replace
          }

          source_image_reference {
            publisher = "Canonical"
            offer     = "0001-com-ubuntu-server-focal"
            sku       = "20_04-lts"
            version   = "latest"
          }

          os_disk {
            name                 = "VM_OS_DISK_NAME"      # replace
            caching              = "ReadWrite"
            storage_account_type = "Premium_LRS"

            # BYOK via Disk Encryption Set
            disk_encryption_set_id = azurerm_disk_encryption_set.DISK_DES.id
          }

          # Example data disk also using BYOK
          data_disk {
            lun                  = 0
            caching              = "ReadOnly"
            disk_size_gb         = 128
            storage_account_type = "Premium_LRS"

            # BYOK via Disk Encryption Set
            disk_encryption_set_id = azurerm_disk_encryption_set.DISK_DES.id
          }
        }
        ```

        This change moves the VM’s OS and data disks from service-managed keys to a customer-managed key via a Disk Encryption Set.\
        Changing an existing VM’s `disk_encryption_set_id` usually forces replacement of the OS/data disks and may recreate the VM, causing downtime; plan carefully before applying.

        To verify, run `terraform plan` and ensure it shows:

        * creation of `azurerm_key_vault`, `azurerm_key_vault_key`, `azurerm_disk_encryption_set`, and `azurerm_key_vault_access_policy`
        * updates (or replacements) to the VM where `os_disk.disk_encryption_set_id` (and any `data_disk[*].disk_encryption_set_id`) are set to the Disk Encryption Set ID.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
