The only constant is change. I noticed some new information came out this month while working on a project that requires encrypting disks. This information significantly changes how Azure Disk Encryption can be applied to Windows and Linux VM’s. This is an update to my previous article on Azure Disk Encryption with the intention of outlining the new, easier method of encrypting Azure disks.
Before we Encrypt
You will need a Key Vault to start with. The Key Vault has to be in the same region as the VM that will be encrypted. My recommendation is to use the Azure Premium Key Vault with Hardware Security Modules (HSM) backed keys. It’s like, $1 US, so it won’t break the bank and gives you a couple more features such as advanced key types. Details on how to setup the Key Vault can be found under “The Key Vault” of this post.
While I’m on the subject, also consider enabling soft delete on the Key Vault. This provides a safeguard from accidental or malicious key deleted. By enabling soft-delete, you can recover deleted keys up to 90 days after they are deleted. Full details here. Below are some basic settings from the mentioned article
To view if soft-delete is enabled log into Azure and use the command below. Soft delete is enabled if it returns True.
$vault = Get-AzureRmKeyVault -VaultName myvault; $vault.EnableSoftDelete
There are two ways to enable Soft Delete. First is at creation of the Key Vault like such:
New-AzureRmKeyVault -VaultName "KeyVaultName" -ResourceGroupName "KeyVaultRG" -Location "westus" -Sky “Premium” -EnableSoftDelete
The commands below will enable Soft Delete on an existing Key Vault. At the time of writing, there is no way to enable the option directly with Set-AzureRMKeyVault. Enabling Soft Delete has to be done with the Azure Resource Manager.
($resource = Get-AzureRmResource -ResourceId (Get-AzureRmKeyVault -VaultName "ContosoVault").ResourceId).Properties | Add-Member -MemberType "NoteProperty" -Name "enableSoftDelete" -Value "true" Set-AzureRmResource -resourceid $resource.ResourceId -Properties $resource.Properties
I did notice the warning shown below in the Key Vault indicating the portal does not support Soft Delete. Viewing and recovering deleted keys will need to be done with PowerShell. Details on those steps can be found here.
Encrypting Disks
There are two major differences from my last post. First, my original post indicated that it was required to use the Key Encryption Key (KEK) method of disk encryption to support Azure Backup and Recovery. That is no longer the case. You can use KEK for added security by using the key to wrap the encryption secrets, BitLocker Encryption Key (BEK) in this case, before writing to the Key Vault. Alternatively, you can bypass the KEK and write the BEK secret directly to the Key Vault. Both options are supported.
Worth noting, you can also import a KEK from your own key management system. More information here.
The second difference from my original post is that you no longer need to configure an Azure AD application to enable disk encryption and, subsequently, Azure AD credentials are no longer needed to enable encryption. The previous method is still supported, but not required. This is a huge improvement in the way disk encryption works and makes it easier to deploy.
Set Advanced Access Policies
The Key Vault needs to be configured for Disk Encryption, as well as for deployments and template deployments if needed. This can be done by going into the Key Vault, Access Policies and selecting “Click here to show advanced access policies” right above “Add new”
This can also be set in PowerShell with the commands below:
Set-AzureRmKeyVaultAccessPolicy -VaultName 'MySecureVault' -ResourceGroupName 'MySecureRG' -EnabledForDiskEncryption Set-AzureRmKeyVaultAccessPolicy -VaultName 'MySecureVault' -ResourceGroupName 'MySecureRG' -EnabledForDeployment Set-AzureRmKeyVaultAccessPolicy -VaultName 'MySecureVault' -ResourceGroupName 'MySecureRG' -EnabledForTemplateDeployment
Create the KEK
Although no longer required, I plan to use a KEK for Azure Disk Encryption on my servers. The Key Vault has been created and Soft Delete enabled. Next step is to create the KEK. The command below will create an HSM KEK. If you are not using the Premium Key Vault, change the -destination value to ‘Software’
$KeyVaultName = 'keyVaultName' $keyEncryptionKeyName = ‘KEKName’ $keyVaultRg = ‘KeyVaultResourceGroup’ $KeyVault = Get-AzureRmKeyVault -VaultName $KeyVaultName -ResourceGroupName $keyVaultRg Add-AzureKeyVaultKey -VaultName $KeyVaultName -Name $keyEncryptionKeyName -Destination ‘HSM’;
Finally, run the commands below to start disk encryption on the server.
Remember to test and run a backup before making any changes to production data. Microsoft’s requirement is to run a backup before encryption for Azure VM’s with managed disks. Once backed up, use the Set-AzureRmVMDiskEncryptionExtention command as outlined below with the -skipVmBackup parameter.
$vmName = 'Test201801' $vmRgName = 'test2018' $diskEncryptionKvUrl = $KeyVault.VaultUri $keyVaultResourceId = $KeyVault.ResourceId $keyEncryptionKeyUrl = (Get-AzureKeyVaultKey -VaultName $keyVaultName -Name $keyEncryptionKeyName).Key.kid; Set-AzureRmVMDiskEncryptionExtension -ResourceGroupName $vmRgName -VMName $vmName -DiskEncryptionKeyVaultUrl $diskEncryptionKvUrl -DiskEncryptionKeyVaultId ` $keyVaultResourceId -KeyEncryptionKeyUrl $keyEncryptionKeyUrl -KeyEncryptionKeyVaultId $KeyVaultResourceId;
Alternatively, you could run BitLocker without the KEK using the command below.
Set-AzureRmVMDiskEncryptionExtension -ResourceGroupName $vmRgName -VMName $vmName -DiskEncryptionKeyVaultUrl $diskEncryptionKvUrl -DiskEncryptionKeyVaultId $keyVaultResourceId;
That’s all there is to it. Keep in mind that Dynamic disks can’t be protected by BitLocker. Storage Space Direct works well as an alternative. Also, Windows will encrypt any drives added to the server after encryption is enabled.
Also, there is still no way to do a single file recovery with encrypted disks. Full server recovery is possible. More information on recovering encrypted servers here.
Disk Encryption with ARM Template
In this section I’m going to extend on the above by enabling disk encryption as part of the template deployment. I will use the same Key Vault and KEK settings as outlined above.
I leveraged the AzureDiskEncryption Extension to accomplish my goal. The QuickStart Template can be found here.
I modified it in my environment to include only what was needed to run BitLocker. The first pass looked like this:
I ran into an issue due to a Domain Join extension causing a restart before BitLocker ran. I had to change the Domain Join restart parameter to prevent a reboot at that stage. The server will reboot as part of disk encryption, that will take care of the Domain Join reboot as well. Simply change the Domain Join “Restart”: option from “True” to “False”
That worked, but I prefer to clean it up for multiple deployments by using template parameters. The final version of the template had the following sections added.
Template Parameters:
"keyVaultURL": { "type": "string", "metadata": { "description": "The URL for the Key Vault used to store the KEK and BEK" } }, "keyVaultResourceId": { "type": "string", "metadata": { "description": "Resource ID for the KeyVault, starts with /subscriptions" } }, "keyEncryptionKeyURL": { "type": "string", "metadata": { "description": "The URL for the KEK that will be used as a wrapper for the BEK" } }
Template Extension
{ "type": "Microsoft.Compute/virtualMachines/extensions", "name": "[concat(parameters('virtualMachineNamePrefix'), copyIndex(1),'/AzureDiskEncryption')]", "location": "[parameters('location')]", "apiVersion": "2018-06-01", "tags": "[parameters('tagValues')]", "copy": { "name": "DiskEncryptionLoop", "count": "[parameters('numberOfInstances')]" }, "dependsOn": [ "[concat('Microsoft.Compute/virtualMachines/', parameters('virtualMachineNamePrefix'), copyIndex(1))]" ], "properties": { "publisher": "Microsoft.Azure.Security", "type": "AzureDiskEncryption", "typeHandlerVersion": "2.2", "autoUpgradeMinorVersion": true, "settings": { "EncryptionOperation": "EnableEncryption", "KeyVaultURL": "[parameters('keyVaultURL')]", "KeyVaultResourceId": "[parameters('keyVaultResourceId')]", "KeyEncryptionKeyURL": "[parameters('keyEncryptionKeyURL')]", "KekVaultResourceId": "[parameters('keyVaultResourceId')]", "VolumeType": "All", "ResizeOSDisk": "false" } } }
Parameters File
"keyVaultURL": { "value": "https://centraldiskencrypkv01.vault.azure.net/" }, "keyVaultResourceId": { "value": "/subscriptions/dd7abc6d-27c2-4030-9046-b9a8c9477e60/resourceGroups/CentralKV01/providers/Microsoft.KeyVault/vaults/CentralDiskEncrypKV01" }, "keyEncryptionKeyURL": { "value": "https://centraldiskencrypkv01.vault.azure.net/keys/MyKeyEncryptionKey/aaae6f6900ae4d398f46eaa15bea193a" }
The full template and parameter file are available on my Github page located here.
20 thoughts on “Azure Disk Encryption, V2”
Nice one Travis. Very well explained.
Thank you!