Post

Improve Azure policy speed

When working with Azure Policy, you may notice that some policies seem slow. However, Azure Policy itself is not slow; rather, some settings—mostly in built-in policies—force a 10-minute wait. Sometimes, this delay is useful, as waiting may be necessary for certain operations. However, in most cases, especially when dealing with private endpoints and private DNS zones, waiting 10 minutes is unnecessary.

Here’s what you should change to accelerate the policy.

DINE

Deploy If Not Exists (DINE) is a possible solution for configuring specific settings on any Azure resource. For example, you can enforce private endpoint DNS configuration without granting permissions to every service principal or user who creates a private endpoint. While you do need to create a user-assigned or system-assigned managed identity for the policy, this is a one-time setup.

Once the policy is deployed, it will automatically configure the DNS settings whenever someone creates a private endpoint, such as for a Blob sub-resource. However, the policy will wait 10 minutes—why? Some resource settings are not available immediately, so a delay is enforced. But this is not the case for private endpoint DNS configuration. To avoid the unnecessary wait, you need to modify the built-in policy so that the DNS configuration is applied immediately after the private endpoint is created.

Policy speed up

Modify the policy

The policy is a built-in policy, so you can’t modify it, but you can create a new one with the same settings with some modification. I don’t want to copy the whole policy, so I will show you the modification what you have to do.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
  "mode": "Indexed",
  "policyRule": {
    "if": {
      "allOf": [
        {
          "field": "type",
          "equals": "Microsoft.Network/privateEndpoints"
        },
        {
          "count": {
            "field": "Microsoft.Network/privateEndpoints/privateLinkServiceConnections[*].groupIds[*]",
            "where": {
              "field": "Microsoft.Network/privateEndpoints/privateLinkServiceConnections[*].groupIds[*]",
              "equals": "blob"
            }
          },
          "greaterOrEquals": 1
        }
      ]
    },
    "then": {
      "effect": "[parameters('effect')]",
      "details": {
        "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups",
        "roleDefinitionIds": [
          "/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7"
        ],
        "deployment": {
          "properties": {
            "mode": "incremental",
            "template": {
 ...........Rest of the policy................

Here is the Official link about the DINE: https://learn.microsoft.com/en-us/azure/governance/policy/concepts/effect-deploy-if-not-exists#deployifnotexists-properties

In this documentation this is the important part:

evaluationDelay (optional)

  • Specifies when the existence of the related resources should be evaluated. The delay is only used for evaluations that are a result of a create or update resource request.
  • Allowed values are AfterProvisioning, AfterProvisioningSuccess, AfterProvisioningFailure, or an ISO 8601 duration between 0 and 360 minutes.
  • The AfterProvisioning values inspect the provisioning result of the resource that was evaluated in the policy rule’s if condition. AfterProvisioning runs after provisioning is complete, regardless of outcome. Provisioning that takes more than six hours, is treated as a failure when determining AfterProvisioning evaluation delays.
  • Default is PT10M (10 minutes).
  • Specifying a long evaluation delay might cause the recorded compliance state of the resource to not update until the next evaluation trigger.

So default wait is 10 minutes, that the deploy will start, but I want it immediately, so I have to set the evaluationDelay to AfterProvisioning. So the policy will start after the provisioning is complete.

1
"evaluationDelay": "AfterProvisioning",

So something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
{
  "mode": "Indexed",
  "policyRule": {
    "if": {
      "allOf": [
        {
          "field": "type",
          "equals": "Microsoft.Network/privateEndpoints"
        },
        {
          "count": {
            "field": "Microsoft.Network/privateEndpoints/privateLinkServiceConnections[*].groupIds[*]",
            "where": {
              "field": "Microsoft.Network/privateEndpoints/privateLinkServiceConnections[*].groupIds[*]",
              "equals": "blob"
            }
          },
          "greaterOrEquals": 1
        }
      ]
    },
    "then": {
      "effect": "[parameters('effect')]",
      "details": {
        "evaluationDelay": "AfterProvisioning",
        "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups",
        "roleDefinitionIds": [
          "/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7"
        ],
        "deployment": {
          "properties": {
            "mode": "incremental",
            "template": {
 ...........Rest of the policy................

This is a simple modification, but it can save you a lot of time. If you have a lot of private endpoints, you can save a lot of time with this modification.

Conclusion

Azure Policy is a powerful tool, but if you not use correctly sometimes it can be slow. Another example why we have to understand what we are using and how we can modify it to fit our needs.

This post is licensed under CC BY 4.0 by the author.