CMK Encryption for Azure Compute Gallery with Packer and Cross-Subscription Image Sharing

Hello,

I need to have double-encryption (Customer-managed key + Platform key) supported for an Azure VM image I am creating with Packer. I have two challenges associated with it:

  1. When publishing into Azure Compute Gallery, is it possible to create disk snapshots before pushing a VM Image Version from a generalised VM? The reason for this is to allow the use of CMK-encrypted source and sharing across subscriptions. If you create a VM image version from a VHD or from a running VM, then all the encryption stuff must be in the same subscription, for both source and target. That’s obviously not what I need to achieve.

So, at least in Az CLI, the process should look something like this:

However, I can’t find any such option in the azure-arm runner. The snapshot option works only when pushing to a Managed Disk. Azure Compute Gallery block does not support it.

Here’s the code I am using:

source "azure-arm" "imageBuild" {
  async_resourcegroup_delete = true
  azure_tags = {
    Env               = "Dev"
    "Image Offer"     = "${var.image_offer}"
    "Image Publisher" = "${var.image_publisher}"
    "Image SKU"       = "${var.image_sku}"
    Task              = "Packer"
  }
  build_key_vault_name                = "${var.build_key_vault_name}"
  build_resource_group_name           = "${var.rgName}"
  client_id                           = "${var.client_id}"
  client_secret                       = "${var.client_secret}"
  communicator                        = "winrm"
  disk_encryption_set_id              = "${var.disk_encryption_set_id}"
  image_offer                         = "${var.image_offer}"
  image_publisher                     = "${var.image_publisher}"
  image_sku                           = "${var.image_sku}"
  os_type                             = "Windows"
  shared_image_gallery_destination {
    subscription        = "${var.subscription_id}"
    gallery_name        = "${var.acgName}"
    image_name          = "${var.image_name}"
    image_version       = "${var.image_version}"
    replication_regions = ["${var.location}"]
    resource_group      = "${var.rgName}"
  }
  shared_image_gallery_replica_count = 1
  subscription_id                    = "${var.subscription_id}"
  tenant_id                          = "${var.tenant_id}"
  vm_size                            = "${var.vmSize}"
  winrm_insecure                     = true
  winrm_timeout                      = "7m"
  winrm_use_ssl                      = true
  winrm_username                     = "packer"
}

build {
  sources = ["source.azure-arm.imageBuild"]

  provisioner "powershell" {
    inline = ["mkdir C:\\Windows\\Azure", "& $env:SystemRoot\\System32\\Sysprep\\Sysprep.exe /oobe /generalize /quiet /quit", "while($true) { $imageState = Get-ItemProperty HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\State | Select ImageState; if($imageState.ImageState -ne 'IMAGE_STATE_GENERALIZE_RESEAL_TO_OOBE') { Write-Output $imageState.ImageState; Start-Sleep -s 10  } else { break } }"]
  }

  post-processor "shell-local" {
    execute_command = ["powershell", "-NoProfile", "{{ .Script }}"]
    script          = "packer_pp2.ps1"
  }
}
  1. I need to enable TrustedLaunch on the VM image.

Unfortunately, I can’t do that. Here’s the code that I am using for a VM Image Definition:

az sig image-definition create -g rg-acg-build ` -r acg_trla ` -i 'Trusted_Launch_Image' ` --features SecurityType=TrustedLaunch ` -p MicrosoftWindowsServer ` -f WindowsServer ` -s 2022-datacenter-g2 ` --os-type Windows ` --os-state Generalized ` --hyper-v-generation V2

Here are the options I am using for the HCL Packer file:

secure_boot_enabled                 = true
vtpm_enabled                        = true

When I do that, the image compiles without problems, but during the Azure Compute Gallery push, I am getting the following error:

==> azure-arm.imageBuild: ERROR: -> InternalOperationError :
 Replication failed in this region due to 'Contract.Assert failed: 
Data model DiskEncryptionSetId '' does not match DiskRP returned 
DiskEncryptionSetId '/subscriptions/[redacted]/resourceGroups/
RG-ACG-BUILD/providers/Microsoft.Compute/
diskEncryptionSets/desPlatform'

Any help or ideas are appreciated!