Azure Disk Encryption with AAD (aka v1 or dual pass) to without AAD (aka v2 or single pass)
Issue description:-
The scenario is that you have your disks (OS disks or Data disks) encrypted with v1 ie ADE with AAD (Azure Active Directory) and now you want to change this to the newly encryption strategy ie with v2 (without AAD and also known as single pass).
Once you change it from v1 to v2 and try to add a new data disk, you may encounter below error:
Failed to update disks for the virtual machine 'XXXX'.
Error: User encryption settings in the VM model are not supported. Please
upgrade Azure Disk Encryption extension version and clear encryption settings
in the VM model.
User encryption settings in the VM model are not supported.
Please upgrade Azure Disk Encryption extension version and clear encryption
settings in the VM model.
Failed to update disks for the virtual machine
'XXXX'. Error: User encryption settings in the VM model are not supported.
Please upgrade Azure Disk Encryption extension version and clear encryption
settings in the VM model.
Steps to repro the issue:
Create a Windows VM and encrypt the OS disk and Data disks using AAD Client-id and Client secret.
1. Create a SPN
2. Create a KeyVault
- Create a secret
- Create a Key
4. Initialize the data disk
5. RDP to the VM and ensure encryption has been completed successfully.Can be checked through GUI or using below command
- manage-bde status
7. Disable the V1 encryption (with AAD Client ID and Client secret)
8. Remove the extension. It is important to do this.
9. Encrypt the VM (OS and data Disks) again with V2 (without AAD Client id and secret) that is by single pass.
10. Ensure disks (OS and Data disk) have been encrypted successfully.
11. Ensure through portal that Azure Disk encryption extension for V2 has been provision successfully.
12. Create a data disk and try to attach it to VM, the disk attachment operation will fail with error specified in issue description.
13. To attach the disk successfully, below is the remediation steps which need to be implemented:
- set value of EncryptionSetting = null which means VM has never been encrypted before. value 'False' means it has,you just disabled ADE.
A. Stop the VM
$vmName='VMName'
$rg='Resource group name'
$vm3 = get-azureRMvm -VMName
$vmName -ResourceGroupName $rg
stop-azureRMvm
-ResourceGroupName $vm3.ResourceGroupName -Name $vm3.Name
|
B. Set encryption setting to null from VM model and start the VM
$vm3 = get-azureRMvm -VMName $vmName -ResourceGroupName
$rg
$vm3.StorageProfile.OsDisk.EncryptionSettings = $null
#Null means the VM has never been encrypted
before.
Update-AzureRMVM -ResourceGroupName $vm3.ResourceGroupName
-VM $vm3
Start-AzureRMVM -name $vmname -ResourceGroupName $rg -Verbose
|
14. Now try to Add the Disk to the VM using Terraform or Powershell (ensure you do not do it through GUI)
resource "azurerm_managed_disk"
"external_1" {
name =
"${var.web_server_name}-disk-02"
location = var.web_server_location
resource_group_name =
azurerm_resource_group.web_server_rg.name
storage_account_type = "Standard_LRS"
create_option = "Empty"
disk_size_gb = "10"
}
resource
"azurerm_virtual_machine_data_disk_attachment"
"external_1" {
managed_disk_id =
azurerm_managed_disk.external_1.id
virtual_machine_id
= azurerm_virtual_machine.web_server.id
lun = "2"
caching = "ReadWrite"
}
|
~~~~Lets perform all of the above activities step by step through Terraform~~~~~~~~
>> From Step 1 to 8 is to provision a KEY Vault and create a client secret
1.Create an Application Registration in AAD.
resource
"azurerm_azuread_application" "diskencryptionapp" {
name = "diskencryptionapp"
}
|
resource
"azurerm_azuread_service_principal" "diskencryptionapp" {
application_id =
azurerm_azuread_application.diskencryptionapp.application_id
}
|
resource
"random_string" "password" {
length
= 32
special = false
}
|
resource
"azuread_application_password" "azureadspnpassword" {
application_id =
azurerm_azuread_application.diskencryptionapp.id
value = random_string.password.result
end_date = "2022-01-01T01:00:00Z"
}
|
output
"client_secret" {
description = "Client Secret"
value
= random_string.password.result
}
|
resource
"azurerm_key_vault" "mykeyvault" {
name =
var.keyvaultname
location = var.web_server_location
resource_group_name =
azurerm_resource_group.web_server_rg.name
enabled_for_deployment = true
enabled_for_disk_encryption = true
enabled_for_template_deployment = true
tenant_id = var.tenant_id
sku {
name = "standard"
}
access_policy {
tenant_id = var.tenant_id
object_id =
data.azurerm_azuread_service_principal.diskencryptionapp.object_id
secret_permissions = [
"Get",
"List",
"Set",
"Delete",
"Recover",
"Backup",
"Restore",
"Purge",
]
key_permissions = [
"Get",
"List",
"Update",
"Create",
"Import",
"Delete",
"Recover",
"Backup",
"Restore",
"WrapKey",
"UnwrapKey",
]
certificate_permissions = [
"Get",
"List",
"Update",
"Create",
"Import",
"Delete",
"Recover",
"Backup",
"Restore",
"ManageContacts",
"ManageIssuers",
"GetIssuers",
"ListIssuers",
"SetIssuers",
"DeleteIssuers",
]
}
access_policy {
tenant_id = var.tenant_id
object_id = var.personalobjectid
secret_permissions = [
"Get",
"List",
"Set",
"Delete",
"Recover",
"Restore",
"Purge",
]
key_permissions = [
"Get",
"List",
"Update",
"Create",
"Import",
"Delete",
"Recover",
"Backup",
"Restore",
"WrapKey",
"UnwrapKey",
]
}
network_acls {
default_action = "Allow"
bypass = "AzureServices"
}
tags = {
environment = "Production"
}
}
|
resource "azurerm_key_vault_secret"
"secret-sauce" {
name
= var.secretname
value
= "password@123"
key_vault_id =
azurerm_key_vault.hpvault01.id
tags = {
environment = "Production"
}
}
|
resource
"azurerm_key_vault_key" "diskencryptionkey" {
name
= "diskencryptionkey"
key_vault_id =
azurerm_key_vault.hpvault01.id
key_type
= "RSA"
key_size
= 2048
key_opts = [
"decrypt",
"encrypt",
"sign",
"unwrapKey",
"verify",
"wrapKey",
]
}
|
9. Create a Resource Group
resource "azurerm_resource_group"
"web_server_rg" {
name = var.web_server_rg
location =
var.web_server_location
}
|
10. Create
a VNET
resource "azurerm_virtual_network"
"web_server_vnet" {
name =
"${var.resource_prefix}-vnet"
location = var.web_server_location
resource_group_name = azurerm_resource_group.web_server_rg.name
address_space = [var.web_server_address_space]
}
|
11. Create
a Subnet
resource "azurerm_subnet" "web_server_subnet"
{
name =
"${var.resource_prefix}-subnet"
resource_group_name =
azurerm_resource_group.web_server_rg.name
virtual_network_name = azurerm_virtual_network.web_server_vnet.name
address_prefix =
var.web_server_address_prefix[0]
}
|
12. Create
a Network interface card
resource "azurerm_network_interface"
"web_server_nic" {
name =
"${var.web_server_name}-nic"
location = var.web_server_location
resource_group_name =
azurerm_resource_group.web_server_rg.name
network_security_group_id =
azurerm_network_security_group.web_server_nsg.id
ip_configuration {
name =
"${var.web_server_name}-ip"
subnet_id =
azurerm_subnet.web_server_subnet.id
private_ip_address_allocation
= "dynamic"
public_ip_address_id =
azurerm_public_ip.web_server_public_ip.id
}
}
|
13. Create
a Public IP
14.Create a NSG
resource "azurerm_public_ip"
"web_server_public_ip" {
name =
"${var.web_server_name}-public-ip"
location = var.web_server_location
resource_group_name = azurerm_resource_group.web_server_rg.name
allocation_method =
var.environment == "production" ? "Static" :
"Dynamic"
}
|
14.Create a NSG
resource "azurerm_network_security_group"
"web_server_nsg" {
name =
"${var.web_server_name}-nsg"
location = var.web_server_location
resource_group_name = azurerm_resource_group.web_server_rg.name
}
|
15. Create
NSG rule for RDP to the VM
resource "azurerm_network_security_rule"
"web_server_nsg_rule_rdp" {
name = "RDP
Inbound"
priority = 100
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range =
"3389"
source_address_prefix =
"*"
destination_address_prefix =
"*"
resource_group_name =
azurerm_resource_group.web_server_rg.name
network_security_group_name = azurerm_network_security_group.web_server_nsg.name
}
|
16. Create
a Windows VM
resource "azurerm_virtual_machine"
"web_server" {
name =
var.web_server_name
location =
var.web_server_location
resource_group_name
= azurerm_resource_group.web_server_rg.name
network_interface_ids
= [azurerm_network_interface.web_server_nic.id]
vm_size =
"Standard_D4s_v3"
availability_set_id
= azurerm_availability_set.avset.id
delete_os_disk_on_termination
= true
delete_data_disks_on_termination = true
storage_image_reference {
publisher =
"MicrosoftSQLServer"
offer = "sql2019-ws2019"
sku = "sqldev"
version = "latest"
}
storage_os_disk {
name =
"${var.web_server_name}-os"
caching = "ReadWrite"
create_option =
"FromImage"
managed_disk_type = "Standard_LRS"
os_type = "Windows"
disk_size_gb = 127
}
os_profile {
computer_name =
var.web_server_name
admin_username =
"admina"
admin_password =
data.azurerm_key_vault_secret.secret-sauce.value
}
os_profile_windows_config {
enable_automatic_upgrades = true
provision_vm_agent = true
}
}
|
>> Step 17 to 20 to create data disk and encrypt it with V1
17. Create
a external Data disk
resource "azurerm_managed_disk"
"external" {
name =
"${var.web_server_name}-disk-01"
location = var.web_server_location
resource_group_name =
azurerm_resource_group.web_server_rg.name
storage_account_type = "Standard_LRS"
create_option = "Empty"
disk_size_gb = "10"
}
|
18. Attach
the Disk to the VM
resource
"azurerm_virtual_machine_data_disk_attachment" "external"
{
managed_disk_id =
azurerm_managed_disk.external.id
virtual_machine_id
= azurerm_virtual_machine.web_server.id
lun = "1"
caching = "ReadWrite"
}
|
19. Initialize the Disk
resource "null_resource"
"Azurediskinitialization_1" {
provisioner
"local-exec" {
command =
"az vm extension set --resource-group
${azurerm_resource_group.web_server_rg.name}
--vm-name ${azurerm_virtual_machine.web_server.name} --name
CustomScriptExtension --publisher Microsoft.Compute --settings qq.json
--version 1.9"
}
}
|
20. Enable Disk encryption using AAD
Client ID and Secret and Key vault (ie V1)
resource "null_resource"
"AzureDiskEncryption_ext_rakserver01_v1" {
provisioner
"local-exec" {
command =
"az vm encryption enable --name
${azurerm_virtual_machine.web_server.name}
--resource-group ${azurerm_resource_group.web_server_rg.name}
--aad-client-id ${data.azurerm_azuread_service_principal.diskencryptionapp.application_id}
--aad-client-secret ${random_string.password.result}
--disk-encryption-keyvault ${data.azurerm_key_vault.hpvault01.name}
--volume-type all"
}
}
|
You will find Disks (OS and data Disks has been encrypted and you will find screenshot like below.
21. Now, we have to disable encryption v1 and remove the respective extension.
resource "null_resource"
"AzureDiskEncryption_disable" {
provisioner
"local-exec" {
command =
"az vm encryption disable --name
${azurerm_virtual_machine.web_server.name}
--resource-group ${azurerm_resource_group.web_server_rg.name} --volume-type all"
}
}
|
resource
"null_resource" "AzureDiskEncryption_extensionRemove" {
provisioner "local-exec" {
command = "az vm extension delete
--vm-name ${azurerm_virtual_machine.web_server.name} -g
${azurerm_resource_group.web_server_rg.name}
-n ${var.extensionName}"
}
}
|
RDP to virtual Machine and ensure manage-bde -status C: shows 0.0% and Conversion Status Fully Decrypted
22. Now remove StorageProfile encryption using powershell.
A. Stop the VM
$vmName='rakdbserver01'
$rg='web-rg'
$vm3 = get-azureRMvm -VMName $vmName -ResourceGroupName $rg
stop-azureRMvm -ResourceGroupName $vm3.ResourceGroupName -Name $vm3.Name
Or through Azure CLI $vmName="rakdbserver01" $rg="web-rg" $vm3 = get-azVM -Name $vmName -ResourceGroupName $rg Stop-AzVM -ResourceGroupName $rg -Name $vmName |
B.Remove encryption settings from VM model and start the VM
$vm3 = get-azureRMvm -VMName $vmName -ResourceGroupName $rg
$vm3.StorageProfile.OsDisk.EncryptionSettings = $null
#Null means the VM has never been encrypted before. False means it has,you just disabled ADE.
Update-AzureRMVM -ResourceGroupName $vm3.ResourceGroupName -VM $vm3
Start-AzureRMVM -name $vmname -ResourceGroupName $rg -Verbose
or through Azure CLI $vmName="rakdbserver01" $rg="web-rg" $vm3 = get-azVM -Name $vmName -ResourceGroupName $rg $vm3.StorageProfile.OsDisk.EncryptionSettings = $null Update-AzVM -ResourceGroupName $vm3.ResourceGroupName -VM $vm3 Start-AzVM -name $vmName -ResourceGroupName $rg -Verbose |
23. Enable Disk encryption with v2
resource
"azurerm_virtual_machine_extension" "vmextensionwindows"
{
count =
"${lower(var.vm_os_type) == "windows" ? 1 : 0}"
name =
"AzureDiskEncryption"
location =
"${var.web_server_location}"
resource_group_name =
"${azurerm_resource_group.web_server_rg.name}"
virtual_machine_name =
"${azurerm_virtual_machine.web_server.name}"
publisher =
"Microsoft.Azure.Security"
type =
"AzureDiskEncryption"
type_handler_version = "${var.type_handler_version ==
"" ? "2.2" : var.type_handler_version}"
auto_upgrade_minor_version = true
settings = <<SETTINGS
{
"EncryptionOperation":
"${var.encrypt_operation}",
"KeyVaultURL":
"${data.azurerm_key_vault.hpvault01.vault_uri}",
"KeyVaultResourceId":
"${data.azurerm_key_vault.hpvault01.id}",
"KeyEncryptionKeyURL":
"${data.azurerm_key_vault_key.diskencryptionkey.id}",
"KekVaultResourceId":
"${data.azurerm_key_vault.hpvault01.id}",
"KeyEncryptionAlgorithm":
"${var.encryption_algorithm}",
"SequenceVersion":
"random_id.my_id.b64",
"VolumeType":
"${var.volume_type}"
}
SETTINGS
}
count =
"${lower(var.vm_os_type) == "linux" ? 1 : 0}"
name = "diskencryptionv2"
location =
"${var.web_server_location}"
resource_group_name =
"${azurerm_resource_group.web_server_rg.name}"
virtual_machine_name =
"${azurerm_virtual_machine.web_server.name}"
publisher =
"Microsoft.Azure.Security"
type =
"AzureDiskEncryptionForLinux"
type_handler_version = "${var.type_handler_version ==
"" ? "1.1" : var.type_handler_version}"
auto_upgrade_minor_version = true
settings = <<SETTINGS
{
"EncryptionOperation":
"${var.encrypt_operation}",
"KeyVaultURL":
"${data.azurerm_key_vault.hpvault01.vault_uri}",
"KeyVaultResourceId":
"${data.azurerm_key_vault.hpvault01.id}",
"KeyEncryptionKeyURL":
"${data.azurerm_key_vault_key.diskencryptionkey.id}",
"KekVaultResourceId":
"${data.azurerm_key_vault.hpvault01.id}",
"KeyEncryptionAlgorithm":
"${var.encryption_algorithm}",
"VolumeType":
"${var.volume_type}"
}
SETTINGS
}
|
We can clearly see that the VM has been encrypted using V2 ie single pass. We have not used AAD but used Key vault key to store the respective encryption key.
24. RDP to the VM and ensure manage-bde -status C: -- shows 100%.
25. Try to add a disk using portal which may get failed with error
"Failed to update disks for the virtual machine 'XXXX'. Error: User encryption settings in the VM model are not supported. Please upgrade Azure Disk Encryption extension version and clear encryption settings in the VM model."
26. To fix above error and to attach disk successfully, implement below steps:
A. Stop the VM
$vmName='rakdbserver01'
$rg='web-rg'
$vm3 = get-azureRMvm -VMName $vmName -ResourceGroupName $rg
stop-azureRMvm -ResourceGroupName $vm3.ResourceGroupName -Name $vm3.Name
|
B. set StorageProfile EncryptionSettings to NULL from VM model and start the VM
$vm3 = get-azureRMvm -VMName $vmName -ResourceGroupName $rg
$vm3.StorageProfile.OsDisk.EncryptionSettings = $null
#Null means the VM has never been encrypted before. False means it has,you just disabled ADE.
Update-AzureRMVM -ResourceGroupName $vm3.ResourceGroupName -VM $vm3
Start-AzureRMVM -name $vmname -ResourceGroupName $rg -Verbose
|
27. Add disk using terraform or powershell, you will observe disk has been added successfully.
resource "azurerm_managed_disk"
"external_1" {
name =
"${var.web_server_name}-rakesh-data-disk-03"
location = var.web_server_location
resource_group_name =
azurerm_resource_group.web_server_rg.name
storage_account_type = "Standard_LRS"
create_option = "Empty"
disk_size_gb = "10"
}
|
resource
"azurerm_virtual_machine_data_disk_attachment"
"external_1" {
managed_disk_id =
azurerm_managed_disk.external_1.id
virtual_machine_id
= azurerm_virtual_machine.web_server.id
lun = "2"
caching = "ReadWrite"
}
|
28. Initialize and format the disk
29. Reboot the VM and check encryption status for newly added disks
-- if all the above steps are done as mentioned then the disk should get encrypted
29. Reboot the VM and check encryption status for newly added disks
-- if all the above steps are done as mentioned then the disk should get encrypted
Supporting code for above TERRAFORM implemetation
DataSource_output.tf File
data "azurerm_azuread_service_principal"
"diskencryptionapp" {
display_name =
"diskencryptionapp"
}
|
data "azurerm_key_vault" "hpvault01" {
name = var.keyvaultname
resource_group_name = azurerm_resource_group.web_server_rg.name
}
|
data "azurerm_key_vault_secret"
"secret-sauce" {
name = var.secretname
vault_uri =
data.azurerm_key_vault.hpvault01.vault_uri
}
|
data "azurerm_key_vault_key"
"diskencryptionkey" {
name = "diskencryptionkey"
key_vault_id =
"${data.azurerm_key_vault.hpvault01.id}"
}
|
output "serviceprincipalApplicationid" {
value =
data.azurerm_azuread_service_principal.diskencryptionapp.application_id
}
|
output "serviceprincipalobjectid" {
value = data.azurerm_azuread_service_principal.diskencryptionapp.object_id
}
|
output "vaultname" {
value =
data.azurerm_key_vault.hpvault01.name
}
|
output "vaultsecretname" {
value =
data.azurerm_key_vault_secret.secret-sauce.name
}
|
output "keyvaultsecretpassword" {
value =
data.azurerm_key_vault_secret.secret-sauce.value
}
|
output "kekname" {
value
="${data.azurerm_key_vault_key.diskencryptionkey.name}"
}
|
output "key_type" {
value
="${data.azurerm_key_vault_key.diskencryptionkey.key_type}"
}
|
output "kek_vault_id" {
value
="${data.azurerm_key_vault_key.diskencryptionkey.key_vault_id}"
}
|
output "kek_uri" {
value
="${data.azurerm_key_vault_key.diskencryptionkey.id}"
}
|
output "client_secret" {
description =
"Client Secret"
value = random_string.password.result
}
|
terraform apply -auto-approve --target=azurerm_azuread_service_principal.diskencryptionapp
terraform apply -auto-approve --target=azuread_application_password.azureadspnpassword
terraform apply -auto-approve --target=azurerm_key_vault_secret.secret-sauce
terraform apply -auto-approve --target=azurerm_key_vault_key.diskencryptionkey
terraform apply -auto-approve --target=azurerm_virtual_machine_data_disk_attachment.external
terraform apply -auto-approve --target=azurerm_network_security_rule.web_server_nsg_rule_rdp
terraform apply -auto-approve --target=null_resource.Azurediskinitialization_1
terraform apply -auto-approve --target=null_resource.AzureDiskEncryption_ext_rakserver01_v1"
- wait for 20 minutes
- VM will reboot and disk encryption will start
- disable encryption settings and remove the extension
terraform apply -auto-approve --target=null_resource.AzureDiskEncryption_disable
wait for 10~15 minutes --
terraform apply -auto-approve --target=null_resource.AzureDiskEncryption_extensionRemove
- upgrade to V2
terraform apply -auto-approve --target=azurerm_virtual_machine_extension.vmextensionwindows
- Add a disk using Powershell and ensure disk added in the VM
- RDP to the portal, initialize and format the disk
- Restart the VM, and ensure disk has been encrypted.
Comments
Post a Comment