Encrypt OS and attached data disks in a virtual machine scale set with the Azure CLI

The Azure CLI is used to create and manage Azure resources from the command line or in scripts. This quickstart shows you how to use the Azure CLI to create and encrypt a virtual machine scale set. For more information on applying Azure Disk encryption to a virtual machine scale set, see Azure Disk Encryption for Virtual Machine Scale Sets.

Use Azure Cloud Shell

Azure hosts Azure Cloud Shell, an interactive shell environment that you can use through your browser. Cloud Shell lets you use either bash or PowerShell to work with Azure services. You can use the Cloud Shell pre-installed commands to run the code in this article without having to install anything on your local environment.

To launch Azure Cloud Shell:

Option Example/Link
Select Try It in the upper-right corner of a code block. Selecting Try It doesn't automatically copy the code to Cloud Shell. Example of Try It for Azure Cloud Shell
Go to https://shell.azure.com or select the Launch Cloud Shell button to open Cloud Shell in your browser. Launch Cloud Shell in a new window
Select the Cloud Shell button on the top-right menu bar in the Azure portal. Cloud Shell button in the Azure portal

To run the code in this article in Azure Cloud Shell:

  1. Launch Cloud Shell.

  2. Select the Copy button on a code block to copy the code.

  3. Paste the code into the Cloud Shell session with Ctrl+Shift+V on Windows and Linux, or Cmd+Shift+V on macOS.

  4. Press Enter to run the code.

If you choose to install and use the CLI locally, this tutorial requires that you are running the Azure CLI version 2.0.31 or later. Run az --version to find the version. If you need to install or upgrade, see Install Azure CLI.

Create a scale set

Before you can create a scale set, create a resource group with az group create. The following example creates a resource group named myResourceGroup in the eastus location:

az group create --name myResourceGroup --location eastus

Now create a virtual machine scale set with az vmss create. The following example creates a scale set named myScaleSet that is set to automatically update as changes are applied, and generates SSH keys if they do not exist in ~/.ssh/id_rsa. A 32Gb data disk is attached to each VM instance, and the Azure Custom Script Extension is used to prepare the data disks with az vmss extension set:

# Create a scale set with attached data disk
az vmss create \
  --resource-group myResourceGroup \
  --name myScaleSet \
  --image UbuntuLTS \
  --upgrade-policy-mode automatic \
  --admin-username azureuser \
  --generate-ssh-keys \
  --data-disk-sizes-gb 32

# Prepare the data disk for use with the Custom Script Extension
az vmss extension set \
  --publisher Microsoft.Azure.Extensions \
  --version 2.0 \
  --name CustomScript \
  --resource-group myResourceGroup \
  --vmss-name myScaleSet \
  --settings '{"fileUris":["https://raw.githubusercontent.com/Azure-Samples/compute-automation-configurations/master/prepare_vm_disks.sh"],"commandToExecute":"./prepare_vm_disks.sh"}'

It takes a few minutes to create and configure all the scale set resources and VMs.

Create an Azure key vault enabled for disk encryption

Azure Key Vault can store keys, secrets, or passwords that allow you to securely implement them in your applications and services. Cryptographic keys are stored in Azure Key Vault using software-protection, or you can import or generate your keys in Hardware Security Modules (HSMs) certified to FIPS 140-2 level 2 standards. These cryptographic keys are used to encrypt and decrypt virtual disks attached to your VM. You retain control of these cryptographic keys and can audit their use.

Define your own unique keyvault_name. Then, create a KeyVault with az keyvault create in the same subscription and region as the scale set, and set the --enabled-for-disk-encryption access policy.

# Provide your own unique Key Vault name
keyvault_name=myuniquekeyvaultname

# Create Key Vault
az keyvault create --resource-group myResourceGroup --name $keyvault_name --enabled-for-disk-encryption

Use an existing Key Vault

This step is only required if you have an existing Key Vault that you wish to use with disk encryption. Skip this step if you created a Key Vault in the previous section.

Define your own unique keyvault_name. Then, updated your KeyVault with az keyvault update and set the --enabled-for-disk-encryption access policy.

# Provide your own unique Key Vault name
keyvault_name=myuniquekeyvaultname

# Create Key Vault
az keyvault update --name $keyvault_name --enabled-for-disk-encryption

Enable encryption

To encrypt VM instances in a scale set, first get some information on the Key Vault resource ID with az keyvault show. These variables are used to then start the encryption process with az vmss encryption enable:

# Get the resource ID of the Key Vault
vaultResourceId=$(az keyvault show --resource-group myResourceGroup --name $keyvault_name --query id -o tsv)

# Enable encryption of the data disks in a scale set
az vmss encryption enable \
    --resource-group myResourceGroup \
    --name myScaleSet \
    --disk-encryption-keyvault $vaultResourceId \
    --volume-type DATA

It may take a minute or two for the encryption process to start.

As the scale set is upgrade policy on the scale set created in an earlier step is set to automatic, the VM instances automatically start the encryption process. On scale sets where the upgrade policy is to manual, start the encryption policy on the VM instances with az vmss update-instances.

Enable encryption using KEK to wrap the key

You can also use a Key Encryption Key for added security when encrypting the virtual machine scale set.

# Get the resource ID of the Key Vault
vaultResourceId=$(az keyvault show --resource-group myResourceGroup --name $keyvault_name --query id -o tsv)

# Enable encryption of the data disks in a scale set
az vmss encryption enable \
    --resource-group myResourceGroup \
    --name myScaleSet \
    --disk-encryption-keyvault $vaultResourceId \
    --key-encryption-key myKEK \
    --key-encryption-keyvault $vaultResourceId \
    --volume-type DATA

Note

The syntax for the value of disk-encryption-keyvault parameter is the full identifier string:
/subscriptions/[subscription-id-guid]/resourceGroups/[resource-group-name]/providers/Microsoft.KeyVault/vaults/[keyvault-name]

The syntax for the value of the key-encryption-key parameter is the full URI to the KEK as in:
https://[keyvault-name].vault.azure.net/keys/[kekname]/[kek-unique-id]

Check encryption progress

To check on the status of disk encryption, use az vmss encryption show:

az vmss encryption show --resource-group myResourceGroup --name myScaleSet

When VM instances are encrypted, the status code reports EncryptionState/encrypted, as shown in the following example output:

[
  {
    "disks": [
      {
        "encryptionSettings": null,
        "name": "myScaleSet_myScaleSet_0_disk2_3f39c2019b174218b98b3dfae3424e69",
        "statuses": [
          {
            "additionalProperties": {},
            "code": "EncryptionState/encrypted",
            "displayStatus": "Encryption is enabled on disk",
            "level": "Info",
            "message": null,
            "time": null
          }
        ]
      }
    ],
    "id": "/subscriptions/guid/resourceGroups/MYRESOURCEGROUP/providers/Microsoft.Compute/virtualMachineScaleSets/myScaleSet/virtualMachines/0",
    "resourceGroup": "MYRESOURCEGROUP"
  }
]

Disable encryption

If you no longer wish to use encrypted VM instances disks, you can disable encryption with az vmss encryption disable as follows:

az vmss encryption disable --resource-group myResourceGroup --name myScaleSet

Next steps

  • In this article, you used the Azure CLI to encrypt a virtual machine scale set. You can also use Azure PowerShell or Azure Resource Manager templates.
  • If you wish to have Azure Disk Encryption applied after another extension is provisioned, you can use extension sequencing.
  • An end-to-end batch file example for Linux scale set data disk encryption can be found here. This example creates a resource group, Linux scale set, mounts a 5-GB data disk, and encrypts the virtual machine scale set.