Deploy an Azure virtual machine with Azure Disk Encryption using Terraform

Security is this modern world is very important. You need to make sure that your Azure environment is as secure as possible. Off course it’s not only the Azure environment you need to secure. If you have virtual machines running, you also need to secure them.

One of the options you have to secure your virtual machines, is to use Azure Disk Encryption. For more information about ADE.

This feature can not only be used for your Azure virtual machines but also for Azure Virtual Desktop Session Hosts.

Azure Disk Encryption can be used on both Linux and Windows virtual machines. On Windows it uses the Bitlocker feature to encrypt both the OS disk and the data disk. It is also integrated with Azure Keyvault, so you can easily manage your disk encryption key’s.

If you have activated Microsoft Defender Cloud, you can see what virtual machines are not encrypted and you can be alerted for this.

Requirements

To be able to use this feature you need the following resources:

  • Azure Keyvault
  • Azure Disk Encryption Set

Azure Keyvault

Before you can use Azure Disk Encryption you need to have a Keyvault in your environment. If you want extra info about Keyvault check the doc’s page.

Very important to know is that Azure Disk Encryption requires to have Purge Protection Enabled to be active.

provider "azurerm" {
  features {} 
}

provider "azurerm" {
  features {}
  alias = "hub"
  subscription_id = var.subscription_id_mgmt
}
provider "azurerm" {
  features {}
  alias = "prod"
  subscription_id = var.subscription_id_prd
}
provider "azurerm" {
  features {}
  alias = "identity"
  subscription_id = var.subscription_id_identity
}
provider "azurerm" {
  features {}
  alias = "avd"
  subscription_id = var.subscription_id_avd
}

data "azurerm_log_analytics_workspace" "law" {
  provider = azurerm.hub
  name = "law-hub-${var.prefix}-01"
  resource_group_name = "rg-${var.env}-${var.prefix}-management-01" 
}
data "azurerm_resource_group" "rg-kv" {
  provider = azurerm.hub
  name = "rg-${var.env}-${var.prefix}-management-01"
}

data "azurerm_client_config" "current" {}
#Keyvault Creation
resource "azurerm_key_vault" "kv" {
  provider = azurerm.hub
  depends_on = [ data.azurerm_resource_group.rg-kv ]
  name                        = "kv-${var.env}-${var.prefix}-99"
  location                    = data.azurerm_resource_group.rg-kv.location
  resource_group_name         = data.azurerm_resource_group.rg-kv.name
  enabled_for_disk_encryption = true
  tenant_id                   = data.azurerm_client_config.current.tenant_id
  soft_delete_retention_days  = 7
  purge_protection_enabled    = true
  enabled_for_deployment = true
  enabled_for_template_deployment = true
  sku_name = "standard"
  tags = {
    "Costcenter"   = "IT"
    "Critical"     = "Yes"
    "Environment"  = "Hub"
    "Solution"     = "Keyvault"
  }  
}
resource "azurerm_monitor_diagnostic_setting" "kv-diag" {
  name               = "diag-keyvault-${var.prefix}"
  target_resource_id = azurerm_key_vault.kv.id
  log_analytics_workspace_id = data.azurerm_log_analytics_workspace.law.id
  
  log {
    category = "AuditEvent"
    enabled  = true

    retention_policy {
      enabled = true
    }
  }
  log {
    category = "AzurePolicyEvaluationDetails"
    enabled  = true

    retention_policy {
      enabled = true
    }
  }

  metric {
    category = "AllMetrics"

    retention_policy {
      enabled = true
    }
  }
}

Azure disk Encryption Set

The next resource we need is the disk encryption set. Disk encryption sets allow you to manage encryption keys using server-side encryption for Standard HDD, Standard SSD, and Premium SSD managed disks

resource "azurerm_disk_encryption_set" "en-set" {
    provider = azurerm.hub
  name                = "des-${var.env}-${var.prefix}-01"
  resource_group_name = data.azurerm_resource_group.rg-kv.name
  location            = data.azurerm_resource_group.rg-kv.location
  key_vault_key_id    = azurerm_key_vault_key.vm-key.id

  identity {
    type = "SystemAssigned"
  }
 
}

##key

resource "azurerm_key_vault_key" "vm-key" {
    provider = azurerm.hub
  name         = "key-hub-vm-01"
  key_vault_id = data.azurerm_key_vault.kv.id
  key_type     = "RSA"
  key_size     = 2048

  depends_on = [
    azurerm_key_vault_access_policy.kv-user
  ]

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

You need to add an access policy for the Disk Encryption Key in your Keyvault.

resource "azurerm_key_vault_access_policy" "kv-access-policy-des" {
    provider = azurerm.hub
  key_vault_id = data.azurerm_key_vault.kv.id
  tenant_id    = data.azurerm_client_config.current.tenant_id
  object_id    = azurerm_disk_encryption_set.en-set.identity.0.principal_id

  key_permissions = [
    "Get",
    "WrapKey",
    "UnwrapKey"
  ]
}

The entire code can be found on my Github.

Now that all prerequisites are place we can deploy an Azure virtual machines and encrypt the disk.

resource "azurerm_network_interface" "nic-vm-mgmt-01" {
  provider = azurerm.hub
    name = "nic-01-vm-${var.prefix}-mgmt-01"
    resource_group_name = data.azurerm_resource_group.hub-shared.name
    location = var.location
    ip_configuration {
      name = "ipconfig1"
      subnet_id = data.azurerm_subnet.snet-hub-shared.id
      private_ip_address_allocation = "Dynamic"

    } 
      tags = {
    "Critical"    = "Yes"
    "Solution"    = "Management"
    "Costcenter"  = "IT"
    "Environment" = "Hub"
  } 
}
resource "azurerm_windows_virtual_machine" "dc1" {
  provider = azurerm.hub
  name = "vm-${var.prefix}-mgmt-01"
  resource_group_name = data.azurerm_resource_group.hub-shared.name
  location = data.azurerm_resource_group.hub-shared.location
  network_interface_ids = [azurerm_network_interface.nic-vm-mgmt-01.id]
  size = "Standard_F2s_v2"
  provision_vm_agent = true
  admin_username = "loc-admin"
  admin_password = ""
  os_disk {
    name = "vm-${var.prefix}-mgmt-01-c"
    caching = "ReadWrite"
    storage_account_type = "Standard_LRS"
    disk_size_gb = 127
    
  }
 source_image_reference {
    publisher = "MicrosoftWindowsDesktop"
    offer     = "office-365"
    sku       = "win10-21h2-avd-m365-g2"
    version   = "latest"
  }
  tags = {
    "Critical"    = "Yes"
    "Solution"    = "Management Server"
    "Costcenter"  = "IT"
    "Environment" = "Shared"
  } 

The Encryption itself can be deployed through an Virtual Machine Extension.

resource "azurerm_virtual_machine_extension" "vmextension" {
    provider = azurerm.hub
  name                       = "ade-vm-${var.env}-${var.prefix}-mgmt-01"
  virtual_machine_id         = azurerm_windows_virtual_machine.dc1.id
  publisher                  = "Microsoft.Azure.Security"
  type                       = "AzureDiskEncryption"
  type_handler_version       = 2.2
  auto_upgrade_minor_version = true

  settings = <<SETTINGS
    {
        "EncryptionOperation": "EnableEncryption",
        "KeyVaultURL": "https://kv-hub-jvn-99.vault.azure.net/",
        "KeyVaultResourceId": "/subscriptions/<your subscriptionidhere>/resourceGroups/rg-hub-jvn-management-01/providers/Microsoft.KeyVault/vaults/kv-hub-jvn-99",                   
        "KeyEncryptionKeyURL": "https://kv-hub-jvn-99.vault.azure.net/keys/key-hub-vm-01/yourkeyid",                  
        "KekVaultResourceId":"/subscriptions/<your subscriptionidhere>/resourceGroups/rg-hub-jvn-management-01/providers/Microsoft.KeyVault/vaults/kv-hub-jvn-99",
        "KeyEncryptionAlgorithm": "RSA-OAEP",
        "VolumeType": "All"
    }
SETTINGS

  
}

After the deployment you can see the encryption in the portal.

This concludes this blogpost about deploying Azure virtual machines and securing the disks with Azure Disk Encryption. If you have any questions about this, feel free to contact me.

Leave a Reply

Your email address will not be published. Required fields are marked *