Here is my situation, I am trying to deploy a legacy Azure Frontdoor instance to the new version of AFD and do it via Terraform.
Here is an excerpt from my locals block for the Firewall policy:
firewall_policy = { policy = { name = "policy" sku_name = "AzureSKU" mode = "prevention" managed_rules_list = [ { type = "Microsoft_DefaultRuleSet" version = "1.1" action = "Block" exclusion = [ { match_variable = "QueryStringArgNames" operator = "Contains" selector = "string1" }, { match_variable = "RequestBodyPostArgNames" operator = "StartsWith" selector = "string2" }, { match_variable = "RequestCookieNames" operator = "EqualsAny" selector = "string3" }, { match_variable = "RequestBodyPostArgNames" operator = "Contains" selector = "string4" } ] override = [ { rule_group_name = "RFI" rule = [ { rule_id = "931130" action = "Block" exclusion = [ { match_variable = "RequestBodyPostArgNames" operator = "Equals" selector = "string1" }, { match_variable = "QueryStringArgNames" operator = "Contains" selector = "string2" }, { match_variable = "QueryStringArgNames" operator = "Contains" selector = "string3" }, { match_variable = "QueryStringArgNames" operator = "Contains" selector = "string4" } ] } ] }, { rule_group_name = "PHP" rule = [ { rule_id = "933100" enabled = false action = "Block" }, { rule_id = "933110" enabled = false action = "Block" }, { rule_id = "933120" enabled = false action = "Block" } ] } ] } ] }
}
As you can see, there are lots of nested objects.
In my main.tf file, I call the following:
module "Azure_FW_Policy_module" { for_each = local.firewall_policy source = "./frontdoorFirewallPolicy" cdn_frontdoor_firewall_policy_name = each.value.name resource_group_name = var.resource_group_name sku_name = each.value.sku_name mode = each.value.mode managed_rules_list = each.value.managed_rules_list managed_rules_exclusion_list = each.value.managed_rules_list.exclusion managed_rules_overide_list = each.value.managed_rules_list.override managed_rules_overide_rule_list = each.value.managed_rules_list.override.rule managed_rules_overide_rule_exclusion_list = each.value.managed_rules_list.override.rule.exclusion managed_rules_overide_rule_group_exclusion_list = each.value.managed_rules_list.override.exclusion custom_rules_list = each.value.custom_rules_list tags = var.tags }
The Module itself has a bunch of dynamic blocks in it, to accomodate the various configurations and looks like this:
resource "azurerm_cdn_frontdoor_firewall_policy" "cdn_frontdoor_firewall_policy" { name = var.cdn_frontdoor_firewall_policy_name resource_group_name = var.resource_group_name sku_name = var.sku_name enabled = var.enabled mode = var.mode custom_block_response_status_code = var.custom_block_response_status_code custom_block_response_body = var.custom_block_response_body request_body_check_enabled = var.request_body_check_enabled tags = var.tags dynamic "managed_rule" { for_each = toset(var.managed_rules_list) content { type = managed_rule.value["type"] version = managed_rule.value["version"] action = managed_rule.value["action"] dynamic "exclusion" { for_each = toset(var.managed_rules_exclusion_list) content { match_variable = exclusion.value["match_variable"] operator = exclusion.value["operator"] selector = exclusion.value["selector"] } } dynamic "override" { for_each = toset(var.managed_rules_overide_list) content { rule_group_name = override.value["rule_group_name"] dynamic "rule" { for_each = toset(var.managed_rules_overide_rule_list) content { rule_id = rule.value["rule_id"] action = rule.value["action"] dynamic "exclusion" { for_each = toset(var.managed_rules_overide_rule_exclusion_list) content { match_variable = exclusion.value["match_variable"] operator = exclusion.value["operator"] selector = exclusion.value["selector"] } } } } dynamic "exclusion" { for_each = toset(var.managed_rules_overide_rule_group_exclusion_list) content { match_variable = exclusion.value["match_variable"] operator = exclusion.value["operator"] selector = exclusion.value["selector"] } } } } } } dynamic "custom_rule" { for_each = toset(var.custom_rules_list) content { name = custom_rule.value["name"] enabled = custom_rule.value["enabled"] priority = custom_rule.value["priority"] type = custom_rule.value["type"] action = custom_rule.value["action"] rate_limit_duration_in_minutes = custom_rule.value["rate_limit_duration_in_minutes"] rate_limit_threshold = custom_rule.value["rate_limit_threshold"] match_condition { match_variable = custom_rule.value["match_variable"] operator = custom_rule.value["operator"] negation_condition = custom_rule.value["negation_condition"] match_values = custom_rule.value["match_values"] } } } }
My issue is that when I run this - I get the following error:
"each.value.managed_rules_list is tuple with 1 element This value does not have any attributes."
Based on my reading, I believe that this is because I need to use the flatten command in Terraform on the firewall_policy element in order to pass this to the module:
However - despite reading the above, I am not sure exactly how I need to call flatten to account for all the nested objects and then how I can pass them to my module, as I have not used this before.