I want to create an Azure PolicyDefinition and I am using the code below:
resource "azurerm_policy_definition" "name-caf-alz-policy-sandbox-denyvnetpeering" {
name = "Audit-AzureHybridBenefit"
display_name = "Unused resources driving cost should be avoided"
description = "Optimize cost by enabling Azure Hybrid Benefit. Leverage this Policy definition as a cost control to reveal Virtual Machines not using AHUB."
mode = "All"
policy_type = "Custom"
policy_rule = file("${path.module}/lib/policy_definitions/policy_definition_es_deny_vnet_peer_cross_sub.json")
management_group_id = data.azurerm_management_group.namemgmtgroup.id
}
When I run this command via Azure DevOps, Terraform Validate, Init, and Plan are working but when I do Terraform Apply I get this error:
creating/updating Policy Definition "Audit-AzureHybridBenefit": policy.DefinitionsClient#CreateOrUpdateAtManagementGroup: Failure responding to request: StatusCode=400 -- Original Error: autorest/azure: Service returned an error. Status=400 Code="InvalidPolicyRule" Message="Failed to parse policy rule: 'Could not find member 'apiVersion' on object of type 'PolicyRuleDefinition'. Path 'apiVersion'.'."
When I change the policy_rule
to
jsonencode(file("${path.module}/lib/policy_definitions/policy_definition_es_deny_vnet_peer_cross_sub.json"))
Error: expanding JSON for policy_rule: JSON: cannot unmarshal string into Go value of type map[string]interface {}
The JSON-file itself works succesfully when creating it via the GUI.
JSON-file itself can be found at
The issue indicates that the Apiversion
property, which is present in the Json file
path you provided, is incompatible. The Structure of Policy defintion Json as specified in this Doc should not always include the apiversion
property.
To verify the issue properly, I've tried adding the Json
policy in the policy rule
of .tf
file and it worked as expected as shown.
provider "azurerm"{
features{}
}
resource "azurerm_policy_definition" "name-caf-alz-policy-sandbox-denyvnetpeering" {
name = "Audit-AzureHybridBenefit"
display_name = "Unused resources driving cost should be avoided"
description = "Optimize cost by enabling Azure Hybrid Benefit. Leverage this Policy definition as a cost control to reveal Virtual Machines not using AHUB."
mode = "All"
policy_type = "Custom"
policy_rule = <<POLICY_RULE
{
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Network/virtualNetworks/virtualNetworkPeerings"
},
{
"field": "Microsoft.Network/virtualNetworks/virtualNetworkPeerings/remoteVirtualNetwork.id",
"notcontains": "[[subscription().id]"
}
]
},
"then": {
"effect": "[[parameters('effect')]"
}
}
POLICY_RULE
}
As you are not using parameters
in the Policy, I have not included the parameters
block below. If required, you may add it to the policyrule
with the following structure to make it work.
parameters = <<PARAMETERS
{
"effect": {
"type": "String",
"metadata": {
"displayName": "Effect",
"description": "Enable or disable the execution of the policy"
},
"allowedValues": [
"Audit",
"Deny",
"Disabled"
],
"defaultValue": "Deny"
}
}
PARAMETERS
Executed terraform init
and validated the configuration using terraform validate
:
Executed terraform apply
:
Created policy definition successfully in the Portal:
Or
if you only want to work with file(path)
function, you don't need to include jsonencode
function because the policy_rule
input to the azurerm_policy_definition
resource should be a map
representing the JSON
structure, not a string
. Make sure the syntax and path has correctly given.