Summary
When trustedLaunch: true and encryptionAtHost: true are both set on a VM template, the plugin drops encryptionAtHost from the ARM deployment template. Azure policy then blocks VM creation because encryption at host is missing.
Root Cause
In AzureVMManagementServiceDelegate.java, the addTrustedLaunch() method replaces the entire securityProfile property on the VM resource instead of merging with it.
The ARM templates (e.g. referenceImageIDTemplateWithManagedDisk.json) correctly set:
"securityProfile": {
"encryptionAtHost": "[if(bool(variables('encryptionAtHost')), json('true'), json('null'))]"
}
But addTrustedLaunch() overwrites this with:
properties.put("securityProfile",
"[if(equals(parameters('securityType'), 'TrustedLaunch'), variables('securityProfileJson'), null())]");
Where securityProfileJson only contains uefiSettings + securityType — no encryptionAtHost:
ObjectNode profileNode = MAPPER.createObjectNode();
ObjectNode settingsNode = MAPPER.createObjectNode();
settingsNode.put("secureBootEnabled", true);
settingsNode.put("vTpmEnabled", true);
profileNode.set("uefiSettings", settingsNode);
profileNode.put("securityType", "[parameters('securityType')]");
variableNode.set("securityProfileJson", profileNode);
Steps to Reproduce
- Configure an Azure VM agent template with:
trustedLaunch: true
encryptionAtHost: true
- A gallery image that requires TrustedLaunch security type
- Trigger agent provisioning
- Deployment fails with
RequestDisallowedByPolicy — Azure policy requires encryption at host, but the deployed ARM template has no encryptionAtHost in the securityProfile
Error
com.azure.core.management.exception.ManagementException: Status code 400,
"error": {
"code": "InvalidTemplateDeployment",
"details": [{
"code": "RequestDisallowedByPolicy",
"message": "Resource 'azure-vmXXXXXX' was disallowed by policy.
Reasons: 'Virtual machines must have encryption at host enabled to protect data at rest.'"
}]
}
Setting trustedLaunch: false is not a workaround because the gallery image itself requires TrustedLaunch, producing:
AzureCloudException: Deployment Failed: Microsoft.Compute/virtualMachines:azure-vmXXXXXX
- BadRequest - The provided gallery image only supports creation of VMs and VM Scale Sets
with 'TrustedLaunch' security type.
Suggested Fix
Include encryptionAtHost in the securityProfileJson variable built by addTrustedLaunch():
profileNode.set("uefiSettings", settingsNode);
profileNode.put("securityType", "[parameters('securityType')]");
profileNode.put("encryptionAtHost", "[bool(variables('encryptionAtHost'))]"); // preserve encryptionAtHost
variableNode.set("securityProfileJson", profileNode);
This ensures the TrustedLaunch security profile merges with (rather than replaces) the encryption-at-host setting.
Environment
- Plugin version: 1103.ve4a_50ca_2c617 (also checked 1105 — same code path)
- Jenkins: CloudBees CI (managed controller)
- Azure region: West US 2
- OS: Windows 11 25H2 (gallery image with TrustedLaunch security type)
Impact
This is a blocking issue for any environment where Azure policy enforces both TrustedLaunch on gallery images and encryption-at-host on VMs — there is no valid combination of plugin settings that passes both policies.
Summary
When
trustedLaunch: trueandencryptionAtHost: trueare both set on a VM template, the plugin dropsencryptionAtHostfrom the ARM deployment template. Azure policy then blocks VM creation because encryption at host is missing.Root Cause
In
AzureVMManagementServiceDelegate.java, theaddTrustedLaunch()method replaces the entiresecurityProfileproperty on the VM resource instead of merging with it.The ARM templates (e.g.
referenceImageIDTemplateWithManagedDisk.json) correctly set:But
addTrustedLaunch()overwrites this with:Where
securityProfileJsononly containsuefiSettings+securityType— noencryptionAtHost:Steps to Reproduce
trustedLaunch: trueencryptionAtHost: trueRequestDisallowedByPolicy— Azure policy requires encryption at host, but the deployed ARM template has noencryptionAtHostin thesecurityProfileError
Setting
trustedLaunch: falseis not a workaround because the gallery image itself requires TrustedLaunch, producing:Suggested Fix
Include
encryptionAtHostin thesecurityProfileJsonvariable built byaddTrustedLaunch():This ensures the TrustedLaunch security profile merges with (rather than replaces) the encryption-at-host setting.
Environment
Impact
This is a blocking issue for any environment where Azure policy enforces both TrustedLaunch on gallery images and encryption-at-host on VMs — there is no valid combination of plugin settings that passes both policies.