我有一个用例,我希望每个子网都有公共 nsg 和 nsg,具体取决于变量 is_nsg 为 true,然后选择每个子网 nsg,否则对子网使用公共 nsg
我的代码为每个子网和公共子网创建 nsg,但无法添加基于交换机的 nsg 关联。下面是我的 nsg.tf
resource "azurerm_network_security_group" "nsg1" { #common nsg
location = var.location
name = var.default_nsg_name
resource_group_name = local.rg_name
}
# nsg's
resource "azurerm_network_security_group" "nsg" { #nsg per subnet
for_each = {
for subnet_key, subnet in local.subnets : subnet_key => subnet
if subnet.is_nsg == true
}
name = each.value.nsg_name
resource_group_name = local.rg_name
location = var.location
dynamic "security_rule" {
for_each = each.value.rules
content {
name = security_rule.value.name
priority = security_rule.value.priority
direction = security_rule.value.direction
access = security_rule.value.access
protocol = security_rule.value.protocol
description = lookup(security_rule.value, "description", null)
source_port_range = lookup(security_rule.value, "source_port_range", null)
source_port_ranges = lookup(security_rule.value, "source_port_ranges", null)
destination_port_range = lookup(security_rule.value, "destination_port_range", null)
destination_port_ranges = lookup(security_rule.value, "destination_port_ranges", null)
source_address_prefix = lookup(security_rule.value, "source_address_prefix", null)
source_address_prefixes = lookup(security_rule.value, "source_address_prefixes", null)
destination_address_prefix = lookup(security_rule.value, "destination_address_prefix", null)
destination_address_prefixes = lookup(security_rule.value, "destination_address_prefixes", null)
}
}
tags = var.tags
lifecycle {
ignore_changes = [
tags["createdDate"]
]
}
}
# nsg associations
resource "azurerm_subnet_network_security_group_association" "nsg_as" {
for_each = {
for assoc in local.subnets : assoc.subnet_key => assoc
}
subnet_id = azurerm_subnet.subnets[each.key].id
network_security_group_id = each.value.is_nsg ? azurerm_network_security_group.nsg[each.key].id : azurerm_network_security_group.nsg1.id
}
这是我的当地人。tf
subnets = length(var.subnets) > 0 ? flatten([
for subnet_key, subnet in var.subnets : {
subnet_key = subnet_key
is_nsg = try(subnet.is_nsg, false) # Assuming default is false
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = subnet.cidr
endpoints = try(subnet.endpoints, [])
enforce_priv_link_service = try(subnet.enforce_priv_link_service, false)
enforce_priv_link_endpoint = try(subnet.enforce_priv_link_endpoint, false)
rules = local.nsg_rules[subnet_key]
subnet_name = try(subnet.name, join("-", [local.naming.subnet, subnet_key]))
nsg_name = try(subnet.nsg_name, join("-", [local.naming.network_security_group, subnet_key]))
rt_name = try(subnet.route_name, join("-", [local.naming.route_table, subnet_key]), {})
location = var.location
routes = try(subnet.route.routes, {})
route_table = local.route_table_info[subnet_key].route_table
shd_route_table = local.route_table_info[subnet_key].shd_route_table
delegations = [for d in try(subnet.delegations, {}) : {
name = d.name
actions = try(d.actions, [])
}]
}
]) : []
这是我的变量.tf
variable "subnets" {
description = "Subnets configuration"
type = any
}
这是调用我的模块的地方
模块“网络”{
default_nsg_name = "${var.prefix}-${var.location_shortcode}-${var.environment}-nsg01" 子网 = local.subnet_config 路由表=本地.路由配置 }
这是我的子网配置
subnet_config = {
aks = {
name = "${var.prefix}-${var.location_shortcode}-${var.environment}-aks-snet"
nsg_name = "${var.prefix}-${var.location_shortcode}-${var.environment}-nsg01"
route_tables = "default"
cidr = var.subnet_cidrs["aks"]
endpoints = local.subnet_common_service_endpoints
is_nsg = false
nsg = {
rules = local.app_nsg_rules
}
}
sqlmi = {
name = "${var.prefix}-${var.location_shortcode}-${var.environment}-sqlmi-snet"
nsg_name = "${var.prefix}-${var.location_shortcode}-${var.environment}-sqlmi-nsg"
route_table = "sqlmi"
cidr = var.subnet_cidrs["sqlmi"]
is_nsg = true
}
}
我收到此错误
╷
│ Error: Invalid index
│
│ on .terraform\modules\network\modules\azure\vnet\nsg.tf line 56, in resource "azurerm_subnet_network_security_group_association" "nsg_as":
│ 56: network_security_group_id = each.value.is_nsg ? azurerm_network_security_group.nsg[each.key].id : azurerm_network_security_group.nsg1.id
│ ├────────────────
│ │ azurerm_network_security_group.nsg is object with 1 attribute "5"
│ │ each.key is "sqlmi"
│
│ The given key does not identify an element in this collection value.
╵
有人可以帮助我吗
我尝试了通用 nsg 和每个子网 nsg,具体取决于变量 is_nsg 是否为 true,然后选择每个子网 nsg,否则使用通用 nsg 进行子网配置,我能够成功配置要求。
要实现这一目标,您需要创建一个适用于所有子网的网络安全组 (NSG),并根据
is_nsg
标志为特定子网创建单独的 NSG。您看到的错误是由 azurerm_network_security_group.nsg
映射的键与 azurerm_subnet_network_security_group_association.nsg_as
资源中使用的键之间的差异引起的。
根据
is_nsg
标志的值,您需要调整 azurerm_subnet_network_security_group_association
资源以引用正确的 NSG ID。
您想要为子网设置网络安全组关联,并为 NSG 创建一些示例入站和出站规则。我修改了 Terraform 配置来满足这些要求。
Terraform 配置:
main:
provider "azurerm" {
features {}
}
module "network" {
source = "./modules/network"
resource_group_name = var.resource_group_name
location = var.location
vnet_name = var.vnet_name
subnet_config = var.subnet_config
}
variable.tf:
variable "resource_group_name" {
description = "Name of the Azure Resource Group"
type = string
}
variable "location" {
description = "Azure region to deploy resources"
type = string
}
variable "vnet_name" {
description = "Name of the Virtual Network"
type = string
}
variable "subnet_config" {
description = "Configuration for subnets"
type = map(object({
name : string
cidr : string
is_nsg : bool
rules : list(object({
name : string
priority : number
direction : string
access : string
protocol : string
source_port_range : string
destination_port_range : string
source_address_prefix : string
destination_address_prefix : string
}))
}))
}
modules/network/main.tf:
resource "azurerm_resource_group" "rg" {
name = var.resource_group_name
location = var.location
}
resource "azurerm_virtual_network" "vnet" {
name = var.vnet_name
address_space = ["10.0.0.0/16"]
location = var.location
resource_group_name = azurerm_resource_group.rg.name
}
# Common NSG
resource "azurerm_network_security_group" "common_nsg" {
name = "common-nsg"
location = var.location
resource_group_name = azurerm_resource_group.rg.name
# Demo inbound rule
security_rule {
name = "allow-inbound-http"
priority = 100
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "80"
source_address_prefix = "*"
destination_address_prefix = "*"
}
# Demo outbound rule
security_rule {
name = "allow-outbound-https"
priority = 200
direction = "Outbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "443"
source_address_prefix = "*"
destination_address_prefix = "*"
}
}
# NSGs for aks and api subnets
resource "azurerm_network_security_group" "specific_nsg" {
for_each = { for k, v in var.subnet_config : k => v if v.is_nsg }
name = "${each.key}-nsg"
location = var.location
resource_group_name = azurerm_resource_group.rg.name
}
resource "azurerm_subnet" "subnet" {
for_each = var.subnet_config
name = each.value.name
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = [each.value.cidr]
}
# NSG associations
resource "azurerm_subnet_network_security_group_association" "nsg_association" {
for_each = var.subnet_config
subnet_id = azurerm_subnet.subnet[each.key].id
network_security_group_id = each.value.is_nsg ? azurerm_network_security_group.specific_nsg[each.key].id : azurerm_network_security_group.common_nsg.id
}
output "vnet_id" {
value = azurerm_virtual_network.vnet.id
}
output "subnet_ids" {
value = { for s in azurerm_subnet.subnet : s.name => s.id }
}
output "nsg_ids" {
value = merge(
{ "common_nsg" = azurerm_network_security_group.common_nsg.id },
{ for k, v in azurerm_network_security_group.specific_nsg : k => v.id }
)
}
modules/network/variable.tf:
variable "resource_group_name" {
description = "The name of the resource group."
type = string
}
variable "location" {
description = "The location/region where the network is created."
type = string
}
variable "vnet_name" {
description = "The name of the virtual network."
type = string
}
variable "subnet_config" {
description = "A map of subnet configurations."
type = map(object({
name : string
cidr : string
is_nsg : bool
rules : list(object({
name : string
priority : number
direction : string
access : string
protocol : string
source_port_range : string
destination_port_range : string
source_address_prefix : string
destination_address_prefix : string
}))
}))
}
输出: