1

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 Answers1

0

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