azureazure-policy

Azure Policy to deploy Metrics centrally - how to recognise compliance?


I'm trying to create a policy to deploy metrics, and I've got some of the way there but a bit stuck.

For each public IP in our tenancy (spread across different subscriptions) we want to deploy a metric in a central monitoring subscription/resource group. I've got that bit working.

What I can't figure out is how to then get the policy to recognize the PIP resources (that have had a linked metric deployed) as being compliant. I tried to use existencecondition but that doesn't seem able to do it, since it can only check in the subscription of the PIP in question.

I thought about tagging the PIP when the metric is created but that seems a bit messy.

My code is below, which successfully deploys the metric but then continues to see the PIP as non-compliant since it has no way of checking. Ideas?

{
  "mode": "All",
  "policyRule": {
    "if": {
      "allOf": [
        {
          "field": "type",
          "equals": "Microsoft.Network/publicIPAddresses"
        }
      ]
    },
    "then": {
      "effect": "deployIfNotExists",
      "details": {
        "roleDefinitionIds": [
          "/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c"
        ],
        "type": "Microsoft.Insights/metricAlerts",
        "existenceCondition": {
          "allOf": []
        },
        "deployment": {
          "properties": {
            "mode": "incremental",
            "template": {
              "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
              "contentVersion": "1.0.0.0",
              "parameters": {
                "resourceName": {
                  "type": "String",
                  "metadata": {
                    "displayName": "resourceName",
                    "description": "Name of the resource"
                  }
                },
                "resourceId": {
                  "type": "String",
                  "metadata": {
                    "displayName": "resourceId",
                    "description": "Resource ID of the resource emitting the metric that will be used for the comparison"
                  }
                },
                "severity": {
                  "type": "String"
                },
                "windowSize": {
                  "type": "String"
                },
                "evaluationFrequency": {
                  "type": "String"
                },
                "autoMitigate": {
                  "type": "String"
                },
                "enabled": {
                  "type": "String"
                },
                "threshold": {
                  "type": "String"
                }
              },
              "variables": {},
              "resources": [
                {
                  "type": "Microsoft.Resources/deployments",
                  "apiVersion": "2022-09-01",
                  "name": "[concat(parameters('resourceName'), '-MetricDeployment')]",
                  "subscriptionId": "{subscriptionID}",
                  "resourceGroup": "{ResourceGroupName}",
                  "properties": {
                    "mode": "Incremental",
                    "template": {
                      "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
                      "contentVersion": "1.0.0.0",
                      "resources": [
                        {
                          "type": "Microsoft.Insights/metricAlerts",
                          "apiVersion": "2018-03-01",
                          "name": "[concat(parameters('resourceName'), '-VipAvailability')]",
                          "location": "global",
                          "tags": {
                            "_deployed_by_amba": true
                          },
                          "properties": {
                            "description": "Metric Alert for Network publicIPAddresses VipAvailability",
                            "severity": "[parameters('severity')]",
                            "enabled": "[parameters('enabled')]",
                            "scopes": [
                              "[parameters('resourceId')]"
                            ],
                            "evaluationFrequency": "[parameters('evaluationFrequency')]",
                            "windowSize": "[parameters('windowSize')]",
                            "criteria": {
                              "allOf": [
                                {
                                  "name": "VipAvailability",
                                  "metricNamespace": "Microsoft.Network/publicIPAddresses",
                                  "metricName": "VipAvailability",
                                  "operator": "LessThan",
                                  "threshold": "[parameters('threshold')]",
                                  "timeAggregation": "Average",
                                  "criterionType": "StaticThresholdCriterion"
                                }
                              ],
                              "odata.type": "Microsoft.Azure.Monitor.SingleResourceMultipleMetricCriteria"
                            },
                            "autoMitigate": "[parameters('autoMitigate')]",
                            "parameters": {
                              "severity": {
                                "value": "[parameters('severity')]"
                              },
                              "windowSize": {
                                "value": "[parameters('windowSize')]"
                              },
                              "evaluationFrequency": {
                                "value": "[parameters('evaluationFrequency')]"
                              },
                              "autoMitigate": {
                                "value": "[parameters('autoMitigate')]"
                              },
                              "enabled": {
                                "value": "[parameters('enabled')]"
                              },
                              "threshold": {
                                "value": "[parameters('threshold')]"
                              }
                            }
                          }
                        }
                      ]
                    }
                  }
                }
              ]
            },
            "parameters": {
              "resourceName": {
                "value": "[field('name')]"
              },
              "resourceId": {
                "value": "[field('id')]"
              },
              "severity": {
                "value": "[parameters('severity')]"
              },
              "windowSize": {
                "value": "[parameters('windowSize')]"
              },
              "evaluationFrequency": {
                "value": "[parameters('evaluationFrequency')]"
              },
              "autoMitigate": {
                "value": "[parameters('autoMitigate')]"
              },
              "enabled": {
                "value": "[parameters('enabled')]"
              },
              "threshold": {
                "value": "[if(contains(field('tags'), '_amba-VipAvailability-threshold-Override_'), field('tags._amba-VipAvailability-threshold-Override_'), parameters('threshold'))]"
              }
            }
          }
        }
      }
    }
  },
  "parameters": {
    "severity": {
      "type": "String",
      "metadata": {
        "displayName": "Severity",
        "description": "Severity of the Alert"
      },
      "allowedValues": [
        "0",
        "1",
        "2",
        "3",
        "4"
      ],
      "defaultValue": "1"
    },
    "windowSize": {
      "type": "String",
      "metadata": {
        "displayName": "Window Size",
        "description": "Window size for the alert"
      },
      "allowedValues": [
        "PT1M",
        "PT5M",
        "PT15M",
        "PT30M",
        "PT1H",
        "PT6H",
        "PT12H",
        "P1D"
      ],
      "defaultValue": "PT5M"
    },
    "evaluationFrequency": {
      "type": "String",
      "metadata": {
        "displayName": "Evaluation Frequency",
        "description": "Evaluation frequency for the alert"
      },
      "allowedValues": [
        "PT1M",
        "PT5M",
        "PT15M",
        "PT30M",
        "PT1H"
      ],
      "defaultValue": "PT1M"
    },
    "autoMitigate": {
      "type": "String",
      "metadata": {
        "displayName": "Auto Mitigate",
        "description": "Auto Mitigate for the alert"
      },
      "allowedValues": [
        "true",
        "false"
      ],
      "defaultValue": "true"
    },
    "enabled": {
      "type": "String",
      "metadata": {
        "displayName": "Alert State",
        "description": "Alert state for the alert"
      },
      "allowedValues": [
        "true",
        "false"
      ],
      "defaultValue": "true"
    },
    "threshold": {
      "type": "String",
      "metadata": {
        "displayName": "Threshold",
        "description": "Threshold for the alert"
      },
      "defaultValue": "90"
    }
  }
}

Solution

  • As I said earlier, the solution lies in tagging resources upon successful deployment of metrics and using the presence of those tags as a compliance marker.

    Azure allows tagging resources as part of a deployment using Microsoft.Resources/tags. This is supported in the deployIfNotExists effect since nested deployments are allowed (as confirmed in the documentation Azure Policy definitions deployIfNotExists effect).

    How?

    In your policy definition, add a nested deployment to apply tags to the PIP resource. Use the Microsoft.Resources/tags resource type to tag the resource with a compliance marker (e.g. complianceStatus: MetricsDeployed)

    example of how to include tagging within the deployment

    {
      "type": "Microsoft.Resources/tags",
      "apiVersion": "2024-03-01",
      "name": "default",
      "scope": "[parameters('resourceId')]",
      "properties": {
        "tags": {
          "complianceStatus": "MetricsDeployed"
        }
      }
    }
    

    your deployment template would look something like this when deploying the metric and tagging the resource

    {
      "resources": [
        {
          "type": "Microsoft.Insights/metricAlerts",
          "apiVersion": "2018-03-01",
          "name": "[concat(parameters('resourceName'), '-VipAvailability')]",
          "location": "global",
          "properties": {
            "description": "Metric Alert for Network publicIPAddresses VipAvailability",
            "severity": "[parameters('severity')]",
            "enabled": "[parameters('enabled')]",
            "scopes": [
              "[parameters('resourceId')]"
            ],
            "evaluationFrequency": "[parameters('evaluationFrequency')]",
            "windowSize": "[parameters('windowSize')]",
            "criteria": {
              "allOf": [
                {
                  "name": "VipAvailability",
                  "metricNamespace": "Microsoft.Network/publicIPAddresses",
                  "metricName": "VipAvailability",
                  "operator": "LessThan",
                  "threshold": "[parameters('threshold')]",
                  "timeAggregation": "Average",
                  "criterionType": "StaticThresholdCriterion"
                }
              ],
              "odata.type": "Microsoft.Azure.Monitor.SingleResourceMultipleMetricCriteria"
            },
            "autoMitigate": "[parameters('autoMitigate')]"
          }
        },
        {
          "type": "Microsoft.Resources/tags",
          "apiVersion": "2024-03-01",
          "name": "default",
          "dependsOn": [
            "[concat(parameters('resourceName'), '-VipAvailability')]"
          ],
          "scope": "[parameters('resourceId')]",
          "properties": {
            "tags": {
              "complianceStatus": "MetricsDeployed"
            }
          }
        }
      ]
    }
    

    Update your existenceCondition in the policy to check for the presence of the tag complianceStatus

    "existenceCondition": {
      "field": "tags['complianceStatus']",
      "equals": "MetricsDeployed"
    }
    

    This ensures compliance is recognized and tracked effectively.

    References: