Recently I’ve been working with Azure Policy and deploying said policies via Infrastructure-as-Code (IaC) through Terraform.

While working through this, I’ve come across a few gotchas that I’d like to share.

Note: I’ll share a larger code-based mini-series in the future.

 

Management Groups

When working in a larger environment, you may have more than one Azure Subscription, and as a result, you may be using Management Groups.

When working with Azure Policy, you can define (aka create) the policy at either the Management Group or Subscription level. More on this in the Policy Initiatives section.

To make my code modular, I’m using a data reference for the azurerm_management_group resource. It looks something like this:

Data Reference to Management Group

Notice that I’m looking up the Management Group via the GUID assigned to the Group ID. As opposed to this next example, where I look up the Policy Definition based on the name.

Data Reference to Policy Definition

We, unfortunately, do not have the same option when it comes to Management Group data references. It would be far easier (and better) if we could use the display_name property versus the group_id, that way if the GUID changes, it’s just a matter of a lookup effectively based on the name.

In an Infrastructure-as-Code (IaC) Continuous Integration & Continuous Deployment (CI/CD) pipeline, this may cause issues, if for some reason the GUID changes on the target Management Group. So keep this in mind. I have asked the Azure Terraform team if we could have this specific resource updated to allow the use of display_name instead of group_id.

 

Policy Initiatives

With Azure Policy, you can create individual policy definitions, and assign (aka apply) them as you need. But one of the recommended practices for managing policies is to create an Initiative even for a single policy.

When creating a Policy Initiative, within the policy_definitions section of the code, we need to specify the policyDefinitionId. That’s fine, however, the public Terraform documentation for azurerm_policy_set_definition has an example that could be improved.

In the public documentation example, it shows that policyDefinitionId has a pattern of “/providers/Microsoft.Authorization/policyDefinitions/e765b5de-1225-4ba3-bd56-1ac6695af988”

Terraform Documentation – Policy Definition ID Example

Note: The GUID is actually the Policy Definition ID. For the policies that Microsoft has provided out-of-the-box, those have GUIDs for names. But, if you’re creating your own custom policies, you have to provide the ‘name’ (which is what this ‘ID’ is) and ‘display_name’ properties.

So what happens is, if you’re using Management Groups, you need to add some additional information to the policyDefinitionId reference, namely (in blue): /providers/Microsoft.Management/managementgroups/${var.MgmtGroupID}/providers/Microsoft.Authorization/policyDefinitions/${var.PolicyDefinitionID}

If you’re just using Subscriptions, then you can use the example from the public documentation provided.

 

Policy Assignments

Policy Assignments are where the policy is applied (either at the Management Group level or Subscription level).

In Terraform we can use the azurerm_policy_assignment resource provider. When using that provider, we need to specify the policy_definition_id (which would be the ID of either an individual policy or the initiative).

To make my code more modular and independently deployable, I use data resource references (just like I showed for the Management Groups).

Data Reference – Policy Definitions

That works for assigning individual policies via code, but I also want to assign a Policy Initiative.

What I discovered, unfortunately, is that the azurerm_policy_set_definition does not support being a data reference. When I tried to include it as a data reference, like so…

Data Reference – Policy Set

… I encountered the following error: “Error: data.azurerm_policy_set_definition.Initiative-Tagging-ID: Provider doesn’t support data source: azurerm_policy_set_definition

Terraform – Policy Set Definition – Data Reference Error

So, at this point in time, we can’t reference an existing Policy Initiative via a data resource lookup. My workaround to this, in this case, was to semi-hard-code the policy_definition_id as follows:

“/providers/Microsoft.Management/managementgroups/${data.azurerm_management_group.Parent.group_id}/providers/Microsoft.Authorization/policySetDefinitions/AE-Initiative-AllResources-EnforceTags”

Note: I used a variable for the Management Group ID, but hard-coded the Policy Definition ID since there was only one I was working with.

This is also something that I have brought up to the Azure Terraform team, to request that we can use the azurerm_policy_set_definition as a data resource, just like we can with azurerm_policy_definition.

 

Conclusion

These are just a few of the things that I’ve come across recently. Hopefully, this helps you with your Terraform journey. If you encounter something similar, I encourage you to share your experiences and code as well, as it’s only together that we’re able to work through challenges like these.