Filter out elements from a json object in in Terraform
Posted on October 19, 2022 by Adrian Wyssmann ‐ 4 min read
We would like to manage our own Azure Policy Initiatives with Terraform. Our own initatives shall be based on existing ones, but without deprecated policies.
What are Azure Policy Initiatives
Azure Policy allows you audit your infrastructure on Azure and enforce compliance.
Through its compliance dashboard, it provides an aggregated view to evaluate the overall state of the environment, with the ability to drill down to the per-resource, per-policy granularity. It also helps to bring your resources to compliance through bulk remediation for existing resources and automatic remediation for new resources.
Policies are grouped in initiatives:
An initiative definition is a collection of policy definitions that are tailored toward achieving a singular overarching goal.
There are several builtin initiatives which are constantly updated. But this also means, some of the policies part of the initiative are deprecated.
How to manage Policy Initiatives with Terraform
azurerm_policy_set_definition form the azurerm provider is the one resource, that manages policy sets or also know as policy initiatives. While the field parameters
is used to provide the policy definition as a JSON object. AS mentioned in the introduction, we want to have our own initiatives - based on existing ones - but without deprecated policies.
Let’s say we want to create an initiative based AzureSecurityCenter initiative, we can use the [azure_policy_set_definition datasource] to access an existing policy
We can then access the parameter
as follows
How to remove deprecated policies using Terraform
So far so good, so let’s see what we get:
This will show you the content:
From there let’s iterate over the root elements, by adding this
However terraform plan
results in this error
This is cause the decoded_policy_set_definition_params
is local, hence
Works and if we adjust the output as follows
We still get the same output:
Now we want to filter out all elements which contain
Following this post the recommended way is to use [lookup]
, which
retrieves the value of a single element from a map, given its key. If the given key does not exist, the given default value is returned instead.
As we want all that don’t have the attribute metadata.deprecated
, we would use this
The result contains all elements, but we are missing the key of the element (the policy name)
So when iterating over the json object we have to read carefully what it tells [here][result types]
The type of brackets around the for expression decide what type of result it produces.
[]
produces a tuple{}
result is an object and you must provide two result expressions that are separated by the=>
symbol
So the adjusted expression is
Which results in this
Now we can use this in our azurerm_policy_set_definition
as an jsonencode
-ed string: