Create an Azure VM with disk encryption

Enable encryption on a new Windows Server VM with PowerShell

Dealing with disk encryption of virtual machine in Azure can seem at first like a daunting task, especially as the official documentation is a bit of a mess.

The documentation is covering different scenario: Windows, Linux, VM from official image, VM build from imported disks, RM template, GUI, CLI…

In this article, I will cover only one case: Enabling disk encryption (BitLocker) on a newly created Windows Server VM using PowerShell.

So first make sure to have Azure PowerShell installed and up to date.


Prerequisites

To be able to use disk encryption on your VM in Azure, you first need to setup few things:

  • Register an application in Azure AD
  • Create a service principal from this application
  • Create an Azure Key Vault
  • Give permission to application on the Key Vault
  • Give permission to Azure platform on the Key Vault

That can sound like a lot but in fact it can be done with few lines of PowerShell.

#Create an Azure AD application and service principal
$aadClientSecret = “5trong1sYourS3cr3t”
$azureAdApplication = New-AzureRmADApplication -DisplayName "Keyvault Encryption App (Do Not Delete)" -HomePage "https://encryptionapp" -IdentifierUris "https://encryptionapp" -Password $aadClientSecret
$servicePrincipal = New-AzureRmADServicePrincipal –ApplicationId $azureAdApplication.ApplicationId

This will create the app in Azure AD and a service principal, that can be then allowed on the Key Vault.

And the Key Vault that can be created like below:

#Create a Key Vault
$keyVaultName = "myKeyVault"
$keyVault = New-AzureRmKeyVault -VaultName $keyVaultName -ResourceGroupName "myResourceGroup" -Location "EastUS"

However when trying to create the Key Vault, I received an error as the service provider was not registered for my subscription.

New-AzureRmKeyVault : The subscription is not registered to use namespace ‘Microsoft.KeyVault’.

I checked the status of this resource provider like this:

Get-AzureRmResourceProvider -ListAvailable | Where-Object ProviderNameSpace -Match "keyvault"
ProviderNamespace : Microsoft.KeyVault
RegistrationState : NotRegistered
ResourceTypes : {vaults, vaults/secrets, vaults/accessPolicies, operations…}
Locations : {North Central US, East US, North Europe, West Europe…}

That confirmed that the provider was not enabled for my subscription, so I just registered it.

Get-AzureRmResourceProvider -ListAvailable | Where-Object ProviderNameSpace -Match "keyvault" | Register-AzureRmResourceProvider
ProviderNamespace : Microsoft.KeyVault
RegistrationState : Registering

After few minutes, the service provider is registered.

ProviderNamespace : Microsoft.KeyVault
RegistrationState : Registered

Once done, I was able to re-run the Key Vault creation and continue.

The next step is to add permissions.

#Add access for the Azure AD application on the Key Vault
Set-AzureRmKeyVaultAccessPolicy -VaultName $keyVaultName -ServicePrincipalName $servicePrincipal.ApplicationId -PermissionsToKeys 'WrapKey' -PermissionsToSecrets 'Set' -ResourceGroupName "myResourceGroup"
#Add access for the Azure platform to access the Key Vault
Set-AzureRmKeyVaultAccessPolicy -VaultName $keyVaultName -EnabledForDiskEncryption

These permissions will allow the VM resource to write the encryption key to the Key Vault and also allow the Azure Disk Encryption service to retrieve it so the disks can be unlocked when the VM starts.

We will also add a Key Encryption Key to the Key Vault, it adds some security but it’s also required if we want to backup the VM with Azure Backup service.

#Add Key Encryption Key (KEK) to the Key Vault
$keyEncryptionKeyName = "myKEK"
$kek = Add-AzureKeyVaultKey -VaultName $keyVaultName -Name $keyEncryptionKeyName -Destination "Software"

That’s all for the prerequisites and we can now use the results to enable disk encryption for the VM.


Disk Encryption Deployment

As I said before, in this article I focus on enabling disk encryption for a newly created Windows Server VM.

I will not go in the details of creating a VM via PowerShell now, but the whole process is in the full script at the end of this article.

So let’s consider that all the required resources have been created, we are now creating the VM config object and then passing it in the New-AzureRmVM cmdlet.

...
#Create a virtual machine configuration
$vmConfig = New-AzureRmVMConfig -VMName $vmName -VMSize $vmSize -AvailabilitySetId $availabilitySet.Id | Set-AzureRmVMOperatingSystem -Windows -ComputerName $vmName -Credential $cred | Set-AzureRmVMSourceImage -PublisherName $imagePublisher -Offer $imageOffer -Skus $vmImageSkus -Version latest | Add-AzureRmVMNetworkInterface -Id $nic.Id | Add-AzureRmVMDataDisk -Name $dataDiskName -Lun 1 -CreateOption Attach -ManagedDiskId $dataDisk.Id
#Create the virtual machine with the configuration
New-AzureRmVM -ResourceGroupName "myResourceGroup" -Location "EastUS" -VM $vmConfig
...

Once the VM is created, we can retrieve it and store it in a variable.

#Get the virtual machine created
$vm = Get-AzureRmVM -ResourceGroupName "myResourceGroup"" -Name $vmName

We can now enable the disk encryption for this new VM.

#Enable disk encryption on the VM for all disks
Set-AzureRmVMDiskEncryptionExtension -ResourceGroupName $resourceGroup.ResourceGroupName -VMName $vm.Name -AadClientID $servicePrincipal.ApplicationId -AadClientSecret $aadClientSecret -DiskEncryptionKeyVaultUrl $keyVault.VaultUri -DiskEncryptionKeyVaultId $keyVault.ResourceId -KeyEncryptionKeyUrl $kek.Key.Kid -KeyEncryptionKeyVaultId $keyVault.ResourceId -VolumeType All -Force

As you can see we just use the Set-AzureRmVMDiskEncryptionExtension cmdlet and pass it the details for the Azure AD app, Key Vault and Key Encryption Key that we created before. The parameter VolumeType ensures that OS and Data disks will all be encrypted with BitLocker.

If you don’t receive any error, the encryption process will start. We can check the encryption status like this:

#Get the status of the encryption on the VM disk
Get-AzureRmVMDiskEncryptionStatus -ResourceGroupName $resourceGroup.ResourceGroupName -VMName $vm.Name

When you connect to the VM, you should be able to see that the VM disks are now protected. You can also go to Control Panel\All Control Panel Items\BitLocker Drive Encryption to check the status of your disks encryption.

Here is the full script that will create the VM and all necessary resources in one resource group that you can just delete when done testing. This script is just for training and testing purpose. It could be used for production, but you might want to adapt the variables and add some error handling.

Note that I added a 5 minutes break before enabling the encryption, because I was getting errors when trying just after the VM creation. The wait time should depend on the VM size.

Also I was not able to find out if it’s possible to enable the disk encryption directly in VM configuration object. But looking at the quick start RM template, the encryption deployment depends on the VM resource, so the VM needs to be created before.

...
name": "UpdateEncryptionSettings",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2015-01-01",
"dependsOn": ["[concat('Microsoft.Compute/virtualMachines/',parameters('vmName'))]"],
...

I hope this quick article will help you to understand the Disk Encryption requirements and process. Please let me know if there are any errors or missing things. The full script is also part of my 70–533 exam prep on GitHub.