Как я могу избежать нескольких циклов с Terraform for_each и dynamici c для ресурса azurerm_network_security_group? - PullRequest
1 голос
/ 26 февраля 2020

У меня есть CSV-файл, подобный приведенному ниже

nsg_name,nsg_rule_name,priority,direction,access,protocol,source_port_range,destination_port_range,source_address_prefix,destination_address_prefix,description
testinsg,testrule,100,Inbound,Allow,Tcp,*,*,*,*,test
testinsg2,testrule2,101,Outbound,Allow,Tcp,*,*,*,*,test

, и блок ресурсов, как показано ниже

resource "azurerm_network_security_group" "this" {
  count               = length(local.nsgs) > 0 && var.create ? length(local.nsgs) : 0
  name                = local.nsgs[count.index].nsg_name
  location            = var.location
  resource_group_name = var.resource_group
  dynamic "security_rule" {
    for_each = [for n in local.nsgs : {
      name                        = n.nsg_rule_name
      priority                    = n.priority
      direction                   = n.direction
      access                      = n.access
      protocol                    = n.protocol
      source_port_range           = n.source_port_range
      destination_port_range      = n.destination_port_range
      source_address_prefix       = n.source_address_prefix
      destination_address_prefix  = n.destination_address_prefix
      description                 = n.description

    }]
    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
      source_port_range           = security_rule.value.source_port_range
      destination_port_range      = security_rule.value.destination_port_range
      source_address_prefix       = security_rule.value.source_address_prefix
      destination_address_prefix  = security_rule.value.destination_address_prefix
      description                 = security_rule.value.description
    }
  }
}

Когда я выполняю планирование / применение, ресурс пытается создать правила, подобные ниже

  # module.nsgs_with_rules.azurerm_network_security_group.this[0] will be created
  + resource "azurerm_network_security_group" "this" {
      + id                  = (known after apply)
      + location            = "southeastasia"
      + name                = "testinsg"
      + resource_group_name = "pub_testing_tf_mofule_env"
      + security_rule       = [
          + {
              + access                                     = "Allow"
              + description                                = "test"
              + destination_address_prefix                 = "*"
              + destination_address_prefixes               = []
              + destination_application_security_group_ids = []
              + destination_port_range                     = "*"
              + destination_port_ranges                    = []
              + direction                                  = "Inbound"
              + name                                       = "testrule"
              + priority                                   = 100
              + protocol                                   = "Tcp"
              + source_address_prefix                      = "*"
              + source_address_prefixes                    = []
              + source_application_security_group_ids      = []
              + source_port_range                          = "*"
              + source_port_ranges                         = []
            },
          + {
              + access                                     = "Allow"
              + description                                = "test"
              + destination_address_prefix                 = "*"
              + destination_address_prefixes               = []
              + destination_application_security_group_ids = []
              + destination_port_range                     = "*"
              + destination_port_ranges                    = []
              + direction                                  = "Outbound"
              + name                                       = "testrule2"
              + priority                                   = 101
              + protocol                                   = "Tcp"
              + source_address_prefix                      = "*"
              + source_address_prefixes                    = []
              + source_application_security_group_ids      = []
              + source_port_range                          = "*"
              + source_port_ranges                         = []
            },
        ]
      + tags                = (known after apply)
    }

  # module.nsgs_with_rules.azurerm_network_security_group.this[1] will be created
  + resource "azurerm_network_security_group" "this" {
      + id                  = (known after apply)
      + location            = "southeastasia"
      + name                = "testinsg2"
      + resource_group_name = "pub_testing_tf_mofule_env"
      + security_rule       = [
          + {
              + access                                     = "Allow"
              + description                                = "test"
              + destination_address_prefix                 = "*"
              + destination_address_prefixes               = []
              + destination_application_security_group_ids = []
              + destination_port_range                     = "*"
              + destination_port_ranges                    = []
              + direction                                  = "Inbound"
              + name                                       = "testrule"
              + priority                                   = 100
              + protocol                                   = "Tcp"
              + source_address_prefix                      = "*"
              + source_address_prefixes                    = []
              + source_application_security_group_ids      = []
              + source_port_range                          = "*"
              + source_port_ranges                         = []
            },
          + {
              + access                                     = "Allow"
              + description                                = "test"
              + destination_address_prefix                 = "*"
              + destination_address_prefixes               = []
              + destination_application_security_group_ids = []
              + destination_port_range                     = "*"
              + destination_port_ranges                    = []
              + direction                                  = "Outbound"
              + name                                       = "testrule2"
              + priority                                   = 101
              + protocol                                   = "Tcp"
              + source_address_prefix                      = "*"
              + source_address_prefixes                    = []
              + source_application_security_group_ids      = []
              + source_port_range                          = "*"
              + source_port_ranges                         = []
            },
        ]
      + tags                = (known after apply)
    }

Но я ищу одно правило, которое я упомянул в CSV для каждого SG, и несколько правил должны применяться, когда я даю дублирующее имя nsg, как показано ниже в CSV

nsg_name,nsg_rule_name,priority,direction,access,protocol,source_port_range,destination_port_range,source_address_prefix,destination_address_prefix,description
testinsg,testrule,100,Inbound,Allow,Tcp,*,*,*,*,test
testinsg,testrule2,101,Outbound,Allow,Tcp,*,*,*,*,test
testinsg,testrule3,103,Outbound,Allow,Tcp,*,*,*,*,test

Я также пытался, как показано ниже, но не работал

dynamic "security_rule" {
        for_each = [for n in local.nsgs[count.index] : {

Может, пожалуйста, помогите по этому вопросу?

1 Ответ

0 голосов
/ 05 марта 2020

Я думаю, что, возможно, понял это, но у меня нет доступа Azure, поэтому я проверил это на ресурсе aws_security_group.

nsgs.csv

nsg_name,nsg_rule_name,priority,direction,access,protocol,source_port_range,destination_port_range,source_address_prefix,destination_address_prefix,description
testinsg,testrule,100,Inbound,Allow,Tcp,*,*,*,*,test
testinsg,testrule2,101,Outbound,Allow,Tcp,*,*,*,*,test
testinsg,testrule3,103,Outbound,Allow,Tcp,*,*,*,*,test
testinsg2,testrule2,101,Outbound,Allow,Tcp,*,*,*,*,test

main.tf

locals {
  # get csv content in a list
  nsgs = csvdecode(file("nsgs.csv"))
  # get all the unique nsg_names
  names = distinct(local.nsgs[*].nsg_name)
  # for each unique name, find all the items in the list
  # with the same name and use the name as the key and set
  # its value to the matching items
  combine = {
    for name in local.names : 
      "${name}" => [
        for nsg in local.nsgs : nsg
        if name == nsg.nsg_name
      ]
  }
}

resource "aws_security_group" "example" {
  for_each = local.combine

  name        = each.key
  description = "test"
  vpc_id      = "test"

  dynamic "ingress" {
    for_each = each.value

    content { 
      from_port = ingress.value["priority"]
      to_port   = ingress.value["priority"]
      protocol  = ingress.value["protocol"]
    }
  }
}
$ terraform plan
  # aws_security_group.example["testinsg"] will be created
  + resource "aws_security_group" "example" {
      + arn                    = (known after apply)
      + description            = "test"
      + egress                 = (known after apply)
      + id                     = (known after apply)
      + ingress                = [
          + {
              + cidr_blocks      = []
              + description      = ""
              + from_port        = 100
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "tcp"
              + security_groups  = []
              + self             = false
              + to_port          = 100
            },
          + {
              + cidr_blocks      = []
              + description      = ""
              + from_port        = 101
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "tcp"
              + security_groups  = []
              + self             = false
              + to_port          = 101
            },
          + {
              + cidr_blocks      = []
              + description      = ""
              + from_port        = 103
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "tcp"
              + security_groups  = []
              + self             = false
              + to_port          = 103
            },
        ]
      + name                   = "testinsg"
      + owner_id               = (known after apply)
      + revoke_rules_on_delete = false
      + vpc_id                 = "test"
    }

  # aws_security_group.example["testinsg2"] will be created
  + resource "aws_security_group" "example" {
      + arn                    = (known after apply)
      + description            = "test"
      + egress                 = (known after apply)
      + id                     = (known after apply)
      + ingress                = [
          + {
              + cidr_blocks      = []
              + description      = ""
              + from_port        = 101
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "tcp"
              + security_groups  = []
              + self             = false
              + to_port          = 101
            },
        ]
      + name                   = "testinsg2"
      + owner_id               = (known after apply)
      + revoke_rules_on_delete = false
      + vpc_id                 = "test"
    }

Plan: 2 to add, 0 to change, 0 to destroy.

, поэтому мы можем использовать ваш ресурс для того же

resource "azurerm_network_security_group" "this" {
  for_each = local.combine

  name                = each.key
  location            = var.location

  # This value has to be unique so let's try setting it to
  # local.combine's key instead of the original static value (var.resource_group)
  # resource_group_name = var.resource_group
  resource_group_name = each.value.key

  dynamic "security_rule" {
    for_each = each.value

    content {
      name                        = security_rule.value["nsg_name"]
      priority                    = security_rule.value["priority"]
      direction                   = security_rule.value["direction"]
      access                      = security_rule.value["access"]
      protocol                    = security_rule.value["protocol"]
      source_port_range           = security_rule.value["source_port_range"]
      destination_port_range      = security_rule.value["destination_port_range"]
      source_address_prefix       = security_rule.value["source_address_prefix"]
      destination_address_prefix  = security_rule.value["destination_address_prefix"]
      description                 = security_rule.value["description"]
    }
  }
}
...