Azure Policy DeployIfNotExists fails to change values

254 Views Asked by At

I'm currently creating an Azure Policy that (is supposed to) deploys Microsoft Defender for Servers with Plan P1 if the current plan is different. Many subscriptions that I have currently have Microsoft Defender for Servers enabled, but use plan P2 instead of P1, so I created a policy with DeployIfNotExists that should change the values to the correct one, but it is not working as expected.

The policy is as follows (I'm using Terraform):

resource "azurerm_policy_definition" "dfservers_policy" {
  name         = "defenderForServers"
  policy_type  = "Custom"
  mode         = "All"
  display_name = "Deploy Azure Defender for servers with plan"
  description  = "Azure Defender for servers provides real-time threat protection for server workloads and generates hardening recommendations as well as alerts about suspicious activities."
  management_group_id = data.azurerm_management_group.root_management_group.id

  metadata = <<METADATA
    {
    "category": "Security Center"
    }

METADATA


  policy_rule = <<POLICY_RULE
 {
    "if": {
      "field": "type",
      "equals": "Microsoft.Resources/subscriptions"
    },
    "then": {
      "effect": "[parameters('effect')]",
      "details": {
        "type": "Microsoft.Security/pricings",
        "name": "VirtualMachines",
        "deploymentScope": "subscription",
        "existenceScope": "subscription",
        "roleDefinitionIds": [
          "/providers/Microsoft.Authorization/roleDefinitions/fb1c8493-542b-48eb-b624-b4c8fea62acd"
        ],
        "existenceCondition": {
          "allOf": [
            {
              "field": "Microsoft.Security/pricings/pricingTier",
              "equals": "Standard"
            },
            {
              "field": "Microsoft.Security/pricings/subPlan",
              "equals": "[parameters('plan_type')]"
            }
          ]
        },
        "deployment": {
          "location": "westeurope",
          "properties": {
            "mode": "incremental",
            "parameters": {
              "plan_type": {
                  "value": "[parameters('plan_type')]"
              }
            },
            "template": {
              "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
              "contentVersion": "1.0.0.0",
              "parameters": {
                "plan_type": {
                  "type": "String",
                  "metadata": {
                    "displayName": "Server Plan Type",
                    "description": "Define which plan type to use. Either P1 or P2"
                  },
                  "allowedValues": [
                    "P1",
                    "P2"
                  ],
                  "defaultValue": "P2"
                }
              },
              "variables": {},
              "resources": [
                {
                  "type": "Microsoft.Security/pricings",
                  "apiVersion": "2018-06-01",
                  "name": "VirtualMachines",
                  "properties": {
                    "pricingTier": "Standard",
                    "subPlan": "[parameters('plan_type')]"
                  }
                }
              ],
              "outputs": {}
            }
          }
        }
      }
    }
  }
POLICY_RULE


  parameters = <<PARAMETERS
 {
    "effect": {
      "type": "String",
      "metadata": {
        "displayName": "Effect",
        "description": "Enable or disable the execution of the policy"
      },
      "allowedValues": [
        "DeployIfNotExists",
        "Disabled"
      ],
      "defaultValue": "DeployIfNotExists"
    },
    "plan_type": {
      "type": "String",
      "metadata": {
        "displayName": "Server Plan Type",
        "description": "Define which plan type to use. Either P1 or P2"
      },
      "allowedValues": [
        "P1",
        "P2"
      ],
      "defaultValue": "P2"
    }
  }
PARAMETERS

}

And the assignment is as follows:

resource "azurerm_management_group_policy_assignment" "dfserver_sandbox_assignment" {
  name         = "Def4ServersSB"
  display_name = "Deploy 'Defender for Servers' with Plan P1"
  location     = var.location

  policy_definition_id = azurerm_policy_definition.dfservers_policy.id
  management_group_id  = data.azurerm_management_group.sandbox_management_group.id

  identity {
    type = "SystemAssigned"
  }

  parameters = jsonencode({
    "plan_type": {
      "value": "P1"
    },
  })
}

I have also attached the Security Admin role to the System Managed Identity as there seems to be a bug regarding it:

# This is needed due to a bug where the automatically created System Managed Identity does not have the required permissions (https://github.com/hashicorp/terraform-provider-azurerm/issues/6486)
resource "azurerm_role_assignment" "ra_dfserver_sandbox" {
  scope                = azurerm_management_group_policy_assignment.dfserver_sandbox_assignment.management_group_id
  role_definition_name = "Security Admin"
  principal_id         = azurerm_management_group_policy_assignment.dfserver_sandbox_assignment.identity[0].principal_id
}

After a bit of time the policy seems to work as expected, picking up a few non-complaint subscriptions: Non compliant subscriptions

I'm also able to create a remediation task and run it successfully: Deployment list

All good then, right? Nah. If go and check the values for the subscription I can see that it is still P2: Old values continue

Maybe there was an error and the parameter is setup as P2 instead of P1? Nope: Deployment Value

Maybe for some reason the deployment didn't run? This is my current thesis, but on the activity log of the values this shows up: Activity Log

Do you guys have any idea why this might be happening? Any light would be really appreciated :)

1

There are 1 best solutions below

0
On BEST ANSWER

Your are using an old API version for Microsoft.Security/pricings, update your template to use API version 2022-03-01