Yousef Imran
Yousef Imran

Reputation: 1167

Azure Policy Compliance - "Compliant" resource groups showing as non-complaint

I have an Azure Policy that applies a resource tag "env:prod" to any resource group that has a "prod" part of its name.

This seems to be working just fine as when I create new resource groups, the tag is applied. And when I remove the tag (modify the resource group) the policy applies it back.

The issue I am having is that these resource groups show non-compliance with the same policy.

Looking at the reason why these resource groups are not compliant, it seems the policy is comparing the resource group name to the tag name.

I don't understand why the policy is making this evaluation for compliance.

Even when I create a remediation task from within the policy compliance details, the task does pick up impacted resource groups, completes successfully, and states (2 out of 2) remediated, and I confirmed the remediation task took action by reviewing the resource groups Activity Logs, but the matter of the fact, these two resource groups always had the required tags that were applied by the policy itself when they were created.

If you may help me understand:

  1. Why is the policy making such an evaluation (comparing resource group name to the tag value)
  2. How can I fix it?

Additional notes:

  1. The resource groups have been created over a week or so ago.
  2. Their compliance as described here has not changed since.

Thanks ahead.

Policy definition:

{
  "mode": "All",
  "policyRule": {
    "if": {
      "allOf": [
        {
          "field": "type",
          "equals": "Microsoft.Resources/subscriptions/resourceGroups"
        },
        {
          "field": "name",
          "contains": "prod"
        }
      ]
    },
    "then": {
      "effect": "modify",
      "details": {
        "roleDefinitionIds": [
          "/providers/microsoft.authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c"
        ],
        "operations": [
          {
            "operation": "addOrReplace",
            "field": "[concat('tags[','env',']')]",
            "value": "prod"
          }
        ]
      }
    }
  },
  "parameters": {}
}

Visual aid: enter image description here

Upvotes: 0

Views: 835

Answers (2)

Niclas
Niclas

Reputation: 1262

Although you already solved your issue, I am just adding some more info for people with the same issue as your conclusion is not entirely correct.

You might want to look into how the policyRule works. In the policyRule, you only proceed if the condition is true, which triggers your then effect. So you defined that name contains prod should be modified if true.

Using this in the policyRule means that you look at the current name of the type (in your case Microsoft.Resources/subscriptions/resourceGroups) and if it contains prod (in the name) then it evaluates to true, which will consider it as non-compliant.

{
  "field": "name",
  "contains": "prod"
}

Policy assignments with audit, auditIfNotExists, or modify effects are considered non-compliant for new, updated, or existing resources when the conditions of the policy rule evaluate to TRUE.

Regarding your screenshot, the the target value is not the "env" tag value, it is the hardcoded value of the ? contains operator. You could potentially have solved it by just using notContains - if you only want to focus on the name of the RG or include the tagging value as you have marked in your solution. However, it is two different things it looks at and is unrelated.

Use the resourceGroup()-function to get the name of the RG:

 {
  "value": "[resourceGroup().name]",
  "contains": "prod"
 }

Upvotes: 1

Yousef Imran
Yousef Imran

Reputation: 1167

I resolved this after trying different combinations on the "if" section of the policy rule.

This worked to resolve the compliance issue:

"if": {
        "allOf": [
          {
            "field": "type",
            "equals": "Microsoft.Resources/subscriptions/resourceGroups"
          },
          {
            "field": "name",
            "contains": "prod"
          },
          {
            "not": {
              "field": "[concat('tags[','env',']')]",
              "equals": "prod"
            }
          }
        ]
      }

Basically adding the "not" part to the evaluation. I initially assumed the Azure Policy evaluation would act like "oh this RG already have that tag with the correct value, I'm going to ignore it" but it seems the logic explicitly and only operates within the conditions you provide. So, I told it to ignore RGs that have the tag with the correct value.

Another day, another tip.

Upvotes: 0

Related Questions