Esta é a minha situação: estou tentando implantar uma instância legada do Azure Frontdoor na nova versão do AFD e fazer isso via Terraform.
Aqui está um trecho do meu bloco locals para a política de Firewall:
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"
}
]
}
]
}
]
}
}
Como você pode ver, há muitos objetos aninhados.
No meu arquivo main.tf, eu chamo o seguinte:
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
}
O módulo em si tem vários blocos dinâmicos para acomodar as várias configurações e se parece com isso:
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"]
}
}
}
}
Meu problema é que quando executo isso, recebo o seguinte erro:
"each.value.managed_rules_list é uma tupla com 1 elemento. Este valor não possui nenhum atributo."
Com base na minha leitura, acredito que isso ocorre porque preciso usar o comando flatten no Terraform no elemento firewall_policy para passar isso ao módulo:
Entretanto, apesar de ler o acima, não tenho certeza de como exatamente devo chamar flatten para contabilizar todos os objetos aninhados e como posso passá-los para meu módulo, pois nunca usei isso antes.
No seu
main.tf
, você está tentando buscar os atributos comoeach.value.managed_rules_list.exclusion
, o que pressupõe quemanaged_rules_list
seja um mapa. No entanto, comomanaged_rules_list
é definido como uma lista, o Terraform o trata como uma tupla, e o acesso direto aos atributos sem especificar um índice não é válido.Para resolver isso, você deve garantir que está buscando os elementos das suas listas corretamente. Isso pode ser feito usando
flatten
a função do Terraform. Ela pode ajudar a gerenciar estruturas profundamente aninhadas, convertendo listas aninhadas em uma única lista plana, facilitando a iteração.Configuração de demonstração:
main.tf:
frontdoorFirewallPolicy/main.tf
Implantação:
Consulte:
https://learn.microsoft.com/en-us/azure/frontdoor/create-front-door-terraform
https://library.tf/modules/T-Systems-MMS/cdn/azurerm/latest
https://developer.hashicorp.com/terraform/linguagem/functions/flatten