这是我的情况,我正在尝试将旧的 Azure Frontdoor 实例部署到新版本的 AFD 并通过 Terraform 执行此操作。
以下是我的本地防火墙策略的摘录:
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"
}
]
}
]
}
]
}
}
如您所见,有很多嵌套对象。
在我的 main.tf 文件中,我调用以下内容:
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
}
模块本身有一堆动态块,以适应各种配置,如下所示:
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"]
}
}
}
}
我的问题是,当我运行这个时 - 我收到以下错误:
“each.value.managed_rules_list 是一个包含 1 个元素的元组,此值没有任何属性。”
根据我的阅读,我认为这是因为我需要在 Terraform 中的 firewall_policy 元素上使用 flatten 命令才能将其传递给模块:
然而 - 尽管阅读了上述内容,我仍不确定我需要如何调用 flatten 来解释所有嵌套对象,然后如何将它们传递给我的模块,因为我以前没有使用过它。
在您的 中
main.tf
,您尝试获取类似 的属性each.value.managed_rules_list.exclusion
,这假设managed_rules_list
是一个映射。但是,由于managed_rules_list
被定义为列表,Terraform 将其视为元组,因此在未指定索引的情况下直接访问属性是无效的。要解决此问题,您应该确保正确获取列表元素。这可以使用 Terraform 的
flatten
功能来完成。该功能可以通过将嵌套列表转换为单个平面列表来帮助管理深度嵌套的结构,从而使其更易于迭代。演示配置:
主文件:
frontdoorFirewallPolicy/main.tf
部署:
参考:
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/language/functions/flatten