terraform-provider-azurerm: azurerm_policy_set_definition update behaviour broken in 2.19 using policy_definition_reference

Community Note

  • Please vote on this issue by adding a šŸ‘ reaction to the original issue to help the community and maintainers prioritize this request
  • Please do not leave ā€œ+1ā€ or ā€œme tooā€ comments, they generate extra noise for issue followers and do not help prioritize the request
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment

Terraform (and AzureRM Provider) Version

Terraform v0.12.28

  • provider.azurerm v2.19.0

Affected Resource(s)

  • azure_policy_set_definition

Terraform Configuration Files

I’m unable to provide all the relevant code due to restrictions on releasing code from the end client.

resource "azurerm_policy_set_definition" "diags" {
  name         = "diagnostics-initiative"
  policy_type  = "Custom"
  display_name = "Apply Default Diagnostic Settings"
  management_group_name           = var.definition_management_group_name

  parameters                      = file("${path.module}/json/diagnostics/_globals/initiative_parameters.json")

  dynamic "policy_definition_reference" {
      for_each = [for item in var.diagnostic_settings: {
              name = item.resource_name
          }
          if item.include_in_initiative==true && item.policy_type =="logs"
      ]

      content {
          policy_definition_id = azurerm_policy_definition.definition["${policy_definition_reference.value.name}_logs"].id
          parameters = {
            eventHubAuthorizationRuleId = "[parameters('eventHubAuthorizationRuleId')]"
            eventHubName = "[parameters('eventHubName')]"
            logsEnabled = "[parameters('logsEnabled')]"
            profileName = "[parameters('profileName')]"
            storageAccountId = "[parameters('storageAccountId')]"
            workspace = "[parameters('workspace')]"
            retentionInDays = "[parameters('retentionInDays')]"

          }
       }

    }

  dynamic "policy_definition_reference" {
      for_each = [for item in var.diagnostic_settings: {
              name = item.resource_name
          }
          if item.include_in_initiative==true && item.policy_type =="metrics"
      ]

      content {
          policy_definition_id = azurerm_policy_definition.definition["${policy_definition_reference.value.name}_metrics"].id
          parameters = {
              eventHubAuthorizationRuleId = "[parameters('eventHubAuthorizationRuleId')]"
                eventHubName = "[parameters('eventHubName')]"
                metricsEnabled = "[parameters('metricsEnabled')]"
                profileName = "[parameters('profileName')]"
                workspace = "[parameters('workspace')]"

          }
       }
    }
}

The input consists of input files containing the following which are created using a for_each against the azurerm_policy_definition resource.

variable "diagnostic_settings" {
    default = {
        # Azure Firewall
        firewall_logs = {
            resource_name = "firewall"
            resource_type = "Microsoft.Network/azureFirewalls"
            display_name = "Azure Firewall Logs"
            policy_type = "logs"
            include_in_initiative = true
        }
        firewall_metrics = {
            resource_name = "firewall"
            resource_type = "Microsoft.Network/azureFirewalls"
            display_name = "Azure Firewall Metrics"
            policy_type = "metrics"
            include_in_initiative = true
        }
    }
}

Expected Behavior

Policy Initiative should have been amended with additional or removal of a policy.

Actual Behavior

When adding/removing items it throws errors on the resource_id as it tries to re-map the resource_ids between different policies.

azurerm_policy_set_definition.diags: Modifying… [id=/providers/Microsoft.Management/managementgroups/sandbox/providers/Microsoft.Authorization/policySetDefinitions/diagnostics-initiative]

Error: creating/updating Policy Set Definition ā€œdiagnostics-initiativeā€: policy.SetDefinitionsClient#CreateOrUpdateAtManagementGroup: Failure responding to request: StatusCode=400 – Original Error: autorest/azure: Service returned an error. Status=400 Code=ā€œDuplicateReferencesInPolicySetā€ Message=ā€œThe policy set definition ā€˜diagnostics-initiative’ request is invalid. Policy set definition contains duplicate policy references. Duplicate reference Ids are ā€˜14127430907021476224’. Please remove any exact duplicates from the policy set definition. Violating policy definition Ids are ā€˜/providers/Microsoft.Management/managementgroups/sandbox/providers/Microsoft.Authorization/policyDefinitions/diag-logic_apps-metrics, /providers/Microsoft.Management/managementgroups/sandbox/providers/Microsoft.Authorization/policyDefinitions/diag-virtual_network-metrics’.ā€

on diagnostics_policies_initiative.tf line 34, in resource ā€œazurerm_policy_set_definitionā€ ā€œdiagsā€: 34: resource ā€œazurerm_policy_set_definitionā€ ā€œdiagsā€ {

Steps to Reproduce

  1. Apply an initiative with multiple policies
  2. Inject an additional policy into the middle of the list OR remove an item from the list
  3. Plan and apply the update

About this issue

  • Original URL
  • State: open
  • Created 4 years ago
  • Reactions: 12
  • Comments: 17

Most upvoted comments

I’m wondering whether setting a unique value in the optional ā€˜reference_id’ will resolve the issue. I believe having that passed in alongside the definition ID may get this to work. Looking at the Security Center initiative, they have the ref ID set to a text string not numeric ID.

I haven’t had time to test that yet, but will let you know once I do.

The solution of adding ā€˜reference_id’ to all the policies referenced in the initiative indeed fixed the Duplicate policy references issue for me too, thanks!

I have tried putting a unique value for reference_id in all of my policy_definition_reference blocks, however it did not appear to fix the issue.

For example, if I remove one policy_definition_reference block from the resource, and then do a plan or apply, it tries to re-map reference_id’s for no apparent reason:

Terraform will perform the following actions:

  # azurerm_policy_set_definition.azure_logging will be updated in-place
  ~ resource "azurerm_policy_set_definition" "azure_logging" {
        id                    = "/providers/Microsoft.Management/managementGroups/xxxxxxxx-a2ac-4c32-bf6b-616810e913c6/providers/Microsoft.Authorization/policySetDefinitions/6c88d2a48ab8479e8697fa4f"
        name                  = "6c88d2a48ab8479e8697fa4f"
        # (7 unchanged attributes hidden)

      ~ policy_definition_reference {
          ~ policy_definition_id = "/providers/Microsoft.Management/managementgroups/xxxxxxxx-a2ac-4c32-bf6b-616810e913c6/providers/Microsoft.Authorization/policyDefinitions/Managed-DAML-ResourceLogs-AutomationAccount" -> "/providers/Microsoft.Management/managementgroups/xxxxxxxx-a2ac-4c32-bf6b-616810e913c6/providers/Microsoft.Authorization/policyDefinitions/Managed-DAML-ResourceLogs-KeyVaults"
          ~ reference_id         = "ResourceLogs-AutomationAccount" -> "ResourceLogs-KeyVaults"
            # (3 unchanged attributes hidden)
        }
      ~ policy_definition_reference {
          ~ policy_definition_id = "/providers/Microsoft.Management/managementgroups/xxxxxxxx-a2ac-4c32-bf6b-616810e913c6/providers/Microsoft.Authorization/policyDefinitions/Managed-DAML-ResourceLogs-CognitaveServices" -> "/providers/Microsoft.Management/managementgroups/xxxxxxxx-a2ac-4c32-bf6b-616810e913c6/providers/Microsoft.Authorization/policyDefinitions/Managed-DAML-ResourceLogs-AutomationAccount"
          ~ reference_id         = "ResourceLogs-CognitaveServices" -> "ResourceLogs-AutomationAccount"
            # (3 unchanged attributes hidden)
        }
      ~ policy_definition_reference {
          ~ policy_definition_id = "/providers/Microsoft.Management/managementgroups/xxxxxxxx-a2ac-4c32-bf6b-616810e913c6/providers/Microsoft.Authorization/policyDefinitions/Managed-DAML-ResourceLogs-DataLakeAnalytics" -> "/providers/Microsoft.Management/managementgroups/xxxxxxxx-a2ac-4c32-bf6b-616810e913c6/providers/Microsoft.Authorization/policyDefinitions/Managed-DAML-ResourceLogs-CognitaveServices"
          ~ reference_id         = "ResourceLogs-DataLakeAnalytics" -> "ResourceLogs-CognitaveServices"
            # (3 unchanged attributes hidden)
        }

Please note how the reference_ids are being re-mapped however I have NOT changed them in my code.

I am running:

Terraform v0.14.11
+ provider registry.terraform.io/hashicorp/archive v2.2.0
+ provider registry.terraform.io/hashicorp/azuread v1.4.0
+ provider registry.terraform.io/hashicorp/azurerm v2.59.0
+ provider registry.terraform.io/hashicorp/random v3.1.0

Hi @bigglesuk69 and @caldwell2000 thanks for your discussions and I just had some experiments about this.

This is truly caused by the reference_id. When you create the set definition without assigning a reference_id, Azure will automatically create one for you and send it back - therefore this attribute is Computed. But in the terraform implementation, we do not ensure this kind bind, which is saying that in a case of a reordering of the policy_definition_reference blocks, terraform will treat your change as you have changed the definition_id, but the reference_id remains the same. In this case, Azure will return error like posted in the description complaining about DuplicateReferencesInPolicySet. And the reason for the reordering should be that you are using a set to iterate the policy_definition_reference. In a hash set, the order is deterministic but not guaranteed, every time you add or remove or change the element of it, the iteration may reorder, and therefore comes this issue.

And also, to work this around, explicitly assigning reference_id by yourself works - this manages the bind between the reference_id and the definition_id, and therefore no duplicate error will pop out.

I am considering that we could change the type of policy_definition_reference from List to Set (but this would be considered as a breaking change), but I am not absolutely sure, is this list of policy_definition_reference guaranteed to be distinct and orderless?

Having the same issue. Is there a workaround or a fix coming soon? Using Versions: Terraform v0.12.21 provider.azurerm v2.25.0