将 nsg 连接到 azure terraform 中的子网

问题描述 投票:0回答:1

我有一个用例,我希望每个子网都有公共 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.
╵

有人可以帮助我吗

azure terraform terraform-provider-azure subnet
1个回答
0
投票

我尝试了通用 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
    }))
  }))
}

输出:

enter image description here

enter image description here

enter image description here

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.