How to define the custom azure policy to enfore azure disk encryption for 100s of machines all at once in a subscription

Maheswararaju P 6 Reputation points
2022-05-19T09:33:47.773+00:00

Hi Everyone,

I am trying to create the remediation for one of the defender for cloud recommendations(VMs should be encrypted with temp disks, cache and the data flowing between vm and storage account) .Can somebody please advise me the solution for below requirements.

  1. How to create the custom policy to enforce Azure disk encryption across all the existing resources( Ex:- I have 100 machines available without azure disk encryption). Here how to define the azure policy with deployIfNotexists as effect parameter.
  2. How to create custom azure policy with Effects Deny. (Ex:- In case if somebody spinning up an Azure VM without enabling the Azure disk encryption, then policy need to prevent the creation of such VMs.) So that future resources would be compliant while creating the VMs.

Looking forward to hearing for the kind response on these.

Thank you,
Raju.

Azure Disk Encryption
Azure Disk Encryption
An Azure service for virtual machines (VMs) that helps address organizational security and compliance requirements by encrypting the VM boot and data disks with keys and policies that are controlled in Azure Key Vault.
174 questions
Azure Policy
Azure Policy
An Azure service that is used to implement corporate governance and standards at scale for Azure resources.
883 questions
0 comments No comments
{count} votes

4 answers

Sort by: Most helpful
  1. Jesse Loudon 336 Reputation points
    2022-05-19T22:02:35.877+00:00

    Hey there

    For a DeployIfNotExists (DINE) policy to provision Azure Disk Encryption (ADE) on VMs:

    • I found this blog post helpful which shows how to do achieve this via ARM Template. Because a DINE policy has a nested ARM template to manage the provisioning of a resource/setting (e.g. Azure Disk Encryption) this is a good starting point to be familiar with the properties of the ARM Template. Also see this link for official ADE ARM template parameter explanation.
    • Check out this DINE policy for provisioning Azure Monitor Agent via VM Extension on AzAdvertizer. You will want the use the same structure and similar existenceCondition to provision Azure Disk Encryption.
    • I would be cautious with using 'Deny' effects where there could be legitimate cases where VMs could be created without ADE (for example in Dev/Test). You can use the below snippet as a starting point for the JSON but recommend having the 'effect' value updated to use a parameter so you can easily change the effect from 'Deny' to 'AuditIfNotExists' or 'DeployIfNotExists' quickly. "then": {
      "effect": "deny"
      }

    Hope this helps!
    Jesse


  2. Sumarigo-MSFT 46,126 Reputation points Microsoft Employee
    2022-05-27T03:13:22.93+00:00

    @Maheswararaju P Firstly, apologies for the delay in responding here and any inconvenience this issue may have caused.

    We currently don’t have a DeployIfNotExists policy to scan for Azure Disk Encryption and deploy the extension if not found on VMs. You could try to create a custom policy like the one I’ve linked below. The policy below scans for the presence of GuestConfiguration extension. You’d instead scan for “AzureDiskEncryption”. Please remember to check that ADE is not found in both dual pass and single pass versions. We don’t want to accidentally install a different version of ADE on a VM using ADE already.

    Policy Name: “Deploy the Windows Guest Configuration extension to enable Guest Configuration assignments on Windows VMs”  
    https://ms.portal.azure.com/#blade/Microsoft_Azure_Policy/PolicyDetailBlade/definitionId/%2Fproviders%2FMicrosoft.Authorization%2FpolicyDefinitions%2F385f5831-96d4-41db-9a3c-cd3af78aaae6  
      
    {  
                        "apiVersion": "2019-07-01",  
                        "name": "[concat(parameters('vmName'), '/AzurePolicyforWindows')]",  
                        "type": "Microsoft.Compute/virtualMachines/extensions",  
                        "location": "[parameters('location')]",  
                        "properties": {  
                          "publisher": "Microsoft.GuestConfiguration",  
                          "type": "ConfigurationforWindows",  
                          "typeHandlerVersion": "1.1",  // For ADE, add another check here for version 2.*  
                          "autoUpgradeMinorVersion": true,  
                          "enableAutomaticUpgrade": true,  
                          "settings": {},  
                          "protectedSettings": {}  
                        }  
                      }  
    

    Regarding the other question for Deny, I am check how that can be done and get back to you.

    Please let us know if you have any further queries. I’m happy to assist you further.

    ----------

    Please do not forget to 206017-screenshot-2021-12-10-121802.png and “up-vote” wherever the information provided helps you, this can be beneficial to other community members.

    0 comments No comments

  3. Maheswararaju P 11 Reputation points
    2022-05-30T07:57:26.457+00:00

    Hi @Sumarigo-MSFT,

    Thanks for your response.

    Please let me know if the below one is suffice the requirement?.If it is, kindly let me know how can i pass the parameters as value separately. Kindly correct me if there were any mistakes/corrections needed here.

    {
    "properties": {
    "displayName": "Azure disk encryption should be enabled with a customer-managed key",
    "policyType": "BuiltIn",
    "mode": "Indexed",
    "description": "Use customer-managed keys to manage the encryption at rest of the contents of your managed disks. By default, the data is encrypted at rest with platform-managed keys, but customer-managed keys are commonly required to meet regulatory compliance standards. Customer-managed keys enable the data to be encrypted with an Azure Key Vault key created and owned by you. You have full control and responsibility for the key lifecycle, including rotation and management. Learn more at https://aka.ms/disks-cmk.",
    "metadata": {
    "category": "Compute",
    "version": "2.0.0"
    },
    "parameters": {
    "effect": {
    "type": "String",
    "metadata": {
    "displayName": "Effect",
    "description": "Deploy if not exists the policy"
    },
    "allowedValues": [
    "Audit",
    "Deny",
    "Disabled"
    "DeployIfNotExists"
    ],
    "defaultValue": "DeployIfNotExists"
    }
    },
    "policyRule": {
    "if": {
    "anyOf": [
    {
    "allOf": [
    {
    "field": "type",
    "equals": "Microsoft.Compute/virtualMachines"
    },
    {
    "field": "Microsoft.Compute/virtualMachines/storageProfile.osDisk.managedDisk.diskEncryptionSet.id",
    "exists": "False"
    }
    ]
    },
    {
    "allOf": [
    {
    "field": "type",
    "equals": "Microsoft.Compute/virtualMachines"
    },
    {
    "value": "[length(field('Microsoft.Compute/virtualMachines/storageProfile.dataDisks'))]",
    "greater": 0
    },
    {
    "field": "Microsoft.Compute/virtualMachines/storageProfile.dataDisks[].managedDisk.id",
    "exists": "False"
    },
    {
    "field": "Microsoft.Compute/virtualMachines/storageProfile.dataDisks[
    ].managedDisk.diskEncryptionSet.id",
    "exists": "False"
    }
    ]
    },
    {
    "allOf": [
    {
    "field": "type",
    "equals": "Microsoft.Compute/disks"
    },
    {
    "field": "Microsoft.Compute/disks/encryption.diskEncryptionSetId",
    "exists": "False"
    }
    ]
    },
    {
    "allOf": [
    {
    "field": "type",
    "equals": "Microsoft.Compute/images"
    },
    {
    "field": "Microsoft.Compute/images/storageProfile.osDisk.diskEncryptionSet.id",
    "exists": "False"
    }
    ]
    },
    {
    "allOf": [
    {
    "field": "type",
    "equals": "Microsoft.Compute/images"
    },
    {
    "value": "[length(field('Microsoft.Compute/images/storageProfile.dataDisks[]'))]",
    "greater": 0
    },
    {
    "not": {
    "field": "Microsoft.Compute/images/storageProfile.dataDisks[
    ].diskEncryptionSet.id",
    "exists": "true"
    }
    }
    ]
    }
    ]
    },
    "then": {
    "effect": "[parameters('effect')]"
    }
    }
    },
    "resources": [
    {
    "type": "Microsoft.Compute/virtualMachines/extensions",
    "name": "[concat(parameters('vmName'),'/', variables('extensionName'))]",
    "location": "[parameters('location')]",
    "apiVersion": "2020-06-01",
    "properties": {
    "publisher": "Microsoft.Azure.Security",
    "type": "[variables('extensionName')]",
    "typeHandlerVersion": "[variables('extensionVersion')]",
    "autoUpgradeMinorVersion": true,
    "forceUpdateTag": "[parameters('forceUpdateTag')]",
    "settings": {
    "EncryptionOperation": "[variables('encryptionOperation')]",
    "KeyVaultURL": "[reference(variables('keyVaultResourceId'), '2019-09-01').vaultUri]",
    "KeyVaultResourceId": "[variables('keyVaultResourceID')]",
    "KeyEncryptionKeyURL": "[parameters('keyEncryptionKeyURL')]",
    "KekVaultResourceId": "[variables('keyVaultResourceID')]",
    "KeyEncryptionAlgorithm": "[variables('keyEncryptionAlgorithm')]",
    "VolumeType": "[parameters('volumeType')]",
    "ResizeOSDisk": "[parameters('resizeOSDisk')]"
    }
    }
    }
    ]
    "id": "/providers/Microsoft.Authorization/policyDefinitions/702dd420-7fcc-42c5-afe8-4026edd20fe0",
    "type": "Microsoft.Authorization/policyDefinitions",
    "name": "702dd420-7fcc-42c5-afe8-4026edd20fe0"
    }

    Thank you,
    Raju.

    0 comments No comments

  4. Maheswararaju P 11 Reputation points
    2022-06-03T14:25:48.027+00:00

    Hi @Sumarigo-MSFT /@JamesTran-MSFT ,

    Hope you are doing well.

    In my current organization, we are leveraging the azure devops pipelines to invoke the policies, so that it would enforce the compliance across resources. I would request you help me with custom policy for above requirement. I have tried to build the policy and wanted to validate but i am unable to do it in a free tier account as VM sizes are not available for all regions.

    {
    "properties": {
    "displayName": "Azure disk encryption should be worked with a customer-managed key",
    "policyType": "Custom",
    "mode": "Indexed",
    "description": "Use customer-managed keys to manage the encryption at rest of the contents of your managed disks. By default, the data is encrypted at rest with platform-managed keys, but customer-managed keys are commonly required to meet regulatory compliance standards. Customer-managed keys enable the data to be encrypted with an Azure Key Vault key created and owned by you. You have full control and responsibility for the key lifecycle, including rotation and management. Learn more at https://aka.ms/disks-cmk.",
    "metadata": {
    "category": "Compute",
    "version": "3.0.0"
    },
    "parameters": {
    "effect": {
    "type": "string",
    "defaultValue": "DeployIfNotExists",
    "allowedValues": [
    "Audit",
    "Deny",
    "Disabled"
    "DeployIfNotExists"
    ],
    "metadata": {
    "displayName": "Effect",
    "description": "Enable or disable the execution of the policy"
    }
    }
    },
    "policyRule": {
    "if": {
    "anyOf": [
    {
    "allOf": [
    {
    "field": "type",
    "equals": "Microsoft.Compute/virtualMachines"
    },
    {
    "field": "Microsoft.Compute/virtualMachines/storageProfile.osDisk.managedDisk.diskEncryptionSet.id",
    "exists": "False"
    }
    ]
    },
    {
    "allOf": [
    {
    "field": "type",
    "equals": "Microsoft.Compute/virtualMachines"
    },
    {
    "value": "[length(field('Microsoft.Compute/virtualMachines/storageProfile.dataDisks'))]",
    "greater": 0
    },
    {
    "field": "Microsoft.Compute/virtualMachines/storageProfile.dataDisks[].managedDisk.id",
    "exists": "False"
    },
    {
    "field": "Microsoft.Compute/virtualMachines/storageProfile.dataDisks[
    ].managedDisk.diskEncryptionSet.id",
    "exists": "False"
    }
    ]
    },
    {
    "allOf": [
    {
    "field": "type",
    "equals": "Microsoft.Compute/disks"
    },
    {
    "field": "Microsoft.Compute/disks/encryption.diskEncryptionSetId",
    "exists": "False"
    }
    ]
    },
    {
    "allOf": [
    {
    "field": "type",
    "equals": "Microsoft.Compute/galleries/images/versions"
    },
    {
    "value": "[length(field('Microsoft.Compute/galleries/images/versions/publishingProfile.targetRegions[].encryption.osDiskImage.diskEncryptionSetId'))]",
    "notEquals": "[length(field('Microsoft.Compute/galleries/images/versions/publishingProfile.targetRegions[
    ]'))]"
    }
    ]
    },
    {
    "allOf": [
    {
    "field": "type",
    "equals": "Microsoft.Compute/galleries/images/versions"
    },
    {
    "value": "[length(field('Microsoft.Compute/galleries/images/versions/storageProfile.dataDiskImages[]'))]",
    "greater": 0
    },
    {
    "anyOf": [
    {
    "count": {
    "field": "Microsoft.Compute/galleries/images/versions/publishingProfile.targetRegions[
    ]",
    "where": {
    "value": "[length(current('Microsoft.Compute/galleries/images/versions/publishingProfile.targetRegions[].encryption.dataDiskImages[].diskEncryptionSetId'))]",
    "notEquals": "[length(field('Microsoft.Compute/galleries/images/versions/storageProfile.dataDiskImages[]'))]"
    }
    },
    "greater": 0
    },
    {
    "not": {
    "field": "Microsoft.Compute/galleries/images/versions/publishingProfile.targetRegions[
    ].encryption.dataDiskImages[].diskEncryptionSetId",
    "exists": "true"
    }
    }
    ]
    }
    ]
    },
    {
    "allOf": [
    {
    "field": "type",
    "equals": "Microsoft.Compute/images"
    },
    {
    "field": "Microsoft.Compute/images/storageProfile.osDisk.diskEncryptionSet.id",
    "exists": "False"
    }
    ]
    },
    {
    "allOf": [
    {
    "field": "type",
    "equals": "Microsoft.Compute/images"
    },
    {
    "value": "[length(field('Microsoft.Compute/images/storageProfile.dataDisks[
    ]'))]",
    "greater": 0
    },
    {
    "not": {
    "field": "Microsoft.Compute/images/storageProfile.dataDisks[*].diskEncryptionSet.id",
    "exists": "true"
    }
    }
    ]
    }
    ]
    },
    "then": {
    "effect": "[parameters('effect')]"
    }
    }
    },
    "deployment": {
    "properties": {
    "mode": "Incremental",
    "template": {
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
    "vmName": {
    "type": "string",
    "metadata": {
    "description": "Name of the virtual machine"
    }
    },
    "keyVaultName": {
    "type": "string",
    "metadata": {
    "description": "Name of the KeyVault to place the volume encryption key"
    }
    },
    "keyVaultResourceGroup": {
    "type": "string",
    "metadata": {
    "description": "Resource group of the KeyVault"
    }
    },
    "keyEncryptionKeyURL": {
    "type": "string",
    "defaultValue": "",
    "metadata": {
    "description": "URL of the KeyEncryptionKey used to encrypt the volume encryption key"
    }
    },
    "location": {
    "type": "string",
    "defaultValue": "[resourceGroup().location]",
    "metadata": {
    "description": "Location for all resources."
    }
    }
    },
    "variables": {
    "extensionName": "AzureDiskEncryption",
    "extensionVersion": "2.2",
    "encryptionOperation": "EnableEncryption",
    "keyEncryptionAlgorithm": "RSA-OAEP",
    "keyVaultResourceID": "[resourceId(parameters('keyVaultResourceGroup'), 'Microsoft.KeyVault/vaults/', parameters('keyVaultName'))]"
    },
    "resources": [
    {
    "type": "Microsoft.Compute/virtualMachines/extensions",
    "name": "[concat(parameters('vmName'),'/', variables('extensionName'))]",
    "location": "[parameters('location')]",
    "apiVersion": "2020-06-01",
    "properties": {
    "publisher": "Microsoft.Azure.Security",
    "type": "[variables('extensionName')]",
    "typeHandlerVersion": "[variables('extensionVersion')]",
    "autoUpgradeMinorVersion": true,
    "settings": {
    "EncryptionOperation": "[variables('encryptionOperation')]",
    "KeyVaultURL": "[reference(variables('keyVaultResourceId'), '2019-09-01').vaultUri]",
    "KeyVaultResourceId": "[variables('keyVaultResourceID')]",
    "KeyEncryptionKeyURL": "[parameters('keyEncryptionKeyURL')]",
    "KekVaultResourceId": "[variables('keyVaultResourceID')]",
    "KeyEncryptionAlgorithm": "[variables('keyEncryptionAlgorithm')]",
    }
    }
    }
    ],
    "outputs":{}
    },
    "parameters": {
    "vmName": {
    "value": "GET-PREREQ-vmName"
    },
    "keyVaultName": {
    "value": "GEN-KEYVAULT-NAME"
    },
    "keyVaultResourceGroup": {
    "value": "GEN-KEYVAULT-RESOURCEGROUP-NAME"
    },
    "keyEncryptionKeyURL": {
    "value": "GEN-KEYVAULT-ENCRYPTION-KEY-URI"
    }
    }
    "id": "/providers/Microsoft.Authorization/policyDefinitions/702dd420-7fcc-42c5-afe8-4026edd20fe0",
    "name": "702dd420-7fcc-42c5-afe8-4026edd20fe0"
    }

    }  
    

    }

    Can you please go through above policy and advise me whether we can enable ADE on multiple machines along with passing the parameters duing run time.

    Looking forward for your kind response.
    Thank you,
    Raju.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.