0
votes

I'm struggling to create a parameterized version of the Azure Policy example which copies Tags applied to a Resource Group to any resources within it. This is the example I'm using as inspiration: https://github.com/Azure/azure-policy/tree/master/samples/ResourceGroup/copy-resourcegroup-tag, which is:

{
    "if": {
        "field": "tags.example",
        "exists": "false"
    },
    "then": {
        "effect": "append",
        "details": [
            {
                "field": "tags.example",
                "value": "[resourceGroup().tags.example]"
            }
        ]
    }
}

We have a number of tags added to Resource Groups, and for billing purposes I need to ensure these are applied to all resources within. I am looking to create an Initiative which contains the same policy several times, each time using a different parameterized tag name. My parameterized version of the example policy looks like this:

"parameters": {
  "tagName": {
    "type": "String",
    "metadata": {
      "displayName": "Tag name",
      "description": "The tag to copy to child resources"
    }
  }
},
"policyRule": {
  "if": {
    "field": "[concat('tags.', parameters('tagName'))]",
    "exists": "false"
  },
  "then": {
    "effect": "append",
    "details": [
      {
        "field": "[concat('tags.', parameters('tagName'))]",
        "value": "[concat('resourceGroup().tags.', parameters('tagName'))]"
      }
    ]
  }
}

When the policy applies I get a result of non-compliant. Viewing the compliance details shows:

Reason for non-compliance
Current value must exist.
Field
tags.ApplicationName
Current value
--

There is a tag called ApplicationName with a value on the Resource Group. The documentation says the reason for "Current value must exist" is the exists condition. This seems counter-intuitive to the way I am expecting this to work - I know it doesn't exist which is why I want to set the value.

Is there any way to debug these beyond assigning the policy and waiting several hours for a result?

Thanks for your help!

1

1 Answers

0
votes

I've figured this out, my syntax was wrong, I need to refer to the Tags using keys rather than as attributes, i.e. tags['ApplicationName'] rather than tags.ApplicationName. The policyRule property needs to be:

"policyRule": {
  "if": {
    "field": "[concat('tags[', parameters('tagName'), ']')]",
    "exists": "false"
  },
  "then": {
    "effect": "append",
    "details": [
      {
        "field": "[concat('tags[', parameters('tagName'), ']')]",
        "value": "[resourceGroup().tags[parameters('tagName')]]"
      }
    ]
  }
}

I also misunderstood how this feature works, it seems that policies with an Append effect can only append at the point of resource creation, not retrospectively on an existing resource. The above policy adds the Tags for new resources but results in a "non-compliant" report for existing resource.

This behavior is as documented here:

"When a policy definition using the append effect is run as part of an evaluation cycle, it doesn't make changes to resources that already exist. Instead, it marks any resource that meets the if condition as non-compliant."