【问题标题】:Terraform (AWS) Creating private acl dynamically with looping logicsTerraform (AWS) 使用循环逻辑动态创建私有 acl
【发布时间】:2020-10-29 02:42:18
【问题描述】:

我正在创建一个 terraform 模块来自动创建 VPC,在该区域可用的每个可用区中都有 1 个公有和私有子网。我成功地为公共子网创建了一个 NACL,通过将它们作为输入(规则映射)允许 80,443,22 入站和出站。

public_acl_rule 的 terraform 块:

resource "aws_network_acl" "public_acl" {
  vpc_id = aws_vpc.main_vpc.id
  subnet_ids = aws_subnet.public_subnet[*].id

  tags = {
    Name = "${var.cluster_name}_public_nacl"
    environment = var.cluster_name
  }
}

resource "aws_network_acl_rule" "public_inbound_acl_rule" {
  count = var.create_public_acl && length(aws_subnet.public_subnet) > 0 ? length(var.public_inbound_acl_rules) : 0

  network_acl_id = aws_network_acl.public_acl.id

  egress = false
  protocol = var.public_inbound_acl_rules[count.index]["protocol"]
  rule_action = var.public_inbound_acl_rules[count.index]["rule_action"]
  rule_number = var.public_inbound_acl_rules[count.index]["rule_number"]
  from_port = lookup(var.public_inbound_acl_rules[count.index], "from_port", null)
  to_port = lookup(var.public_inbound_acl_rules[count.index], "to_port", null)
  icmp_code = lookup(var.public_inbound_acl_rules[count.index], "icmp_code", null)
  icmp_type = lookup(var.public_inbound_acl_rules[count.index], "icmp_type", null)
  cidr_block = lookup(var.public_inbound_acl_rules[count.index], "cidr_block", null)

}

resource "aws_network_acl_rule" "public_outbound_acl_rule" {
  count = var.create_public_acl && length(aws_subnet.public_subnet) > 0 ? length(var.public_outbound_acl_rules) : 0

  network_acl_id = aws_network_acl.public_acl.id

  egress = true
  protocol = var.public_outbound_acl_rules[count.index]["protocol"]
  rule_action = var.public_outbound_acl_rules[count.index]["rule_action"]
  rule_number = var.public_outbound_acl_rules[count.index]["rule_number"]
  from_port = lookup(var.public_outbound_acl_rules[count.index], "from_port", null)
  to_port = lookup(var.public_outbound_acl_rules[count.index], "to_port", null)
  icmp_code = lookup(var.public_outbound_acl_rules[count.index], "icmp_code", null)
  icmp_type = lookup(var.public_outbound_acl_rules[count.index], "icmp_type", null)
  cidr_block = lookup(var.public_outbound_acl_rules[count.index], "cidr_block", null)

}

我尝试了以下带有内联块的 aws_network_acl 来迭代 public_cidr 块:

resource "aws_network_acl" "private_acl" { vpc_id = aws_vpc.main_vpc.id subnet_ids = aws_subnet.private_subnet[*].id for_each = aws_subnet.private_subnet ingress { count = length(var.private_inbound_acl_rules) protocol = var.private_inbound_acl_rules[count.index]["protocol"]
rule_action = var.private_inbound_acl_rules[count.index]["rule_action"] rule_number = var.private_inbound_acl_rules[count.index]["rule_number"] from_port = lookup(var.private_inbound_acl_rules[count.index], "from_port", null) to_port = lookup(var.private_inbound_acl_rules[count.index],
"to_port", null) cidr_block = aws_subnet.public_subnet.cidr_block } tags = { Name = "${var.cluster_name}_private_nacl" environment = var.cluster_name } }

cidr_block 正在请求对 private_inbound_acl_rule 的引用,因为它在计数中提到。

关于如何动态输入公共 cidr_block 作为源并输入私有 nacl 的 acl 规则作为用户输入的任何想法?甚至有可能实现它吗?请分享一些想法。

【问题讨论】:

    标签: amazon-web-services security terraform amazon-vpc vpc


    【解决方案1】:

    我通过稍微改变用例解决了我面临的问题。 用例修改:

    1. 遍历公共 cidr_block 范围以创建私有子网的 NACL 规则。

    2. 要动态获取输入,如果 ssh 的规则,需要启用 db 连接并根据条件创建规则。

    我通过下面的代码实现了同样的效果:

    ## This rule is the enable ssh from public subnet to private subnet##
    resource "aws_network_acl_rule" "private_inbound_ssh_rule" {
    
      network_acl_id = aws_network_acl.private_acl.id
      for_each = var.enable_private_ssh ? toset(aws_subnet.public_subnet[*].cidr_block) : []
    
      egress = false
      protocol = var.private_inbound_ssh_rules["protocol"]
      rule_action = var.private_inbound_ssh_rules["rule_action"]
      rule_number = var.private_inbound_ssh_rules["rule_number"]+tonumber(substr(each.value, 5, 1))
      from_port = lookup(var.private_inbound_ssh_rules, "from_port", null)
      to_port = lookup(var.private_inbound_ssh_rules, "to_port", null)
      cidr_block = each.value
    }
    
    
    ## This rule is the enable db connection from public subnet to private subnet##
    resource "aws_network_acl_rule" "private_inbound_mysql_rule" {
    
      network_acl_id = aws_network_acl.private_acl.id
      for_each = var.enable_private_mysql? toset(aws_subnet.public_subnet[*].cidr_block) : []
    
      egress = false
      protocol = var.private_inbound_mysql_rules["protocol"]
      rule_action = var.private_inbound_mysql_rules["rule_action"]
      rule_number = var.private_inbound_mysql_rules["rule_number"]+tonumber(substr(each.value,5,1))
      from_port = lookup(var.private_inbound_mysql_rules, "from_port", null)
      to_port = lookup(var.private_inbound_mysql_rules, "to_port", null)
      cidr_block = each.value
    }

    【讨论】:

      【解决方案2】:

      从 Terraform 0.12 开始,您可以使用 Dynamic Nested Blocks

      locals {
        nacl_rules = [
          { port : 22,   rule_num : 100, cidr : "0.0.0.0/0" },
          { port : 80,   rule_num : 110, cidr : "0.0.0.0/0" },
          { port : 443,  rule_num : 120, cidr : "0.0.0.0/0" }
        ]
      }
      
      resource "aws_network_acl" "public_tier" {
        vpc_id = aws_vpc.my_vpc.id
        subnet_ids = [for s in aws_subnet.public : s.id]
      
        dynamic "ingress" {
          for_each = [for rule_obj in local.nacl_rules : {
            port       = rule_obj.port
            rule_no    = rule_obj.rule_num
            cidr_block = rule_obj.cidr
          }]
          content {
            protocol   = "tcp"
            rule_no    = ingress.value["rule_no"]
            action     = "allow"
            cidr_block = ingress.value["cidr_block"]
            from_port  = ingress.value["port"]
            to_port    = ingress.value["port"]
          }
        }
      
        dynamic "egress" {
          for_each = [for rule_obj in local.nacl_rules : {
            port       = rule_obj.port
            rule_no    = rule_obj.rule_num
            cidr_block = rule_obj.cidr
          }]
          content {
            protocol   = "tcp"
            rule_no    = egress.value["rule_no"]
            action     = "allow"
            cidr_block = egress.value["cidr_block"]
            from_port  = egress.value["port"]
            to_port    = egress.value["port"]
          }
        }
      
      
        tags = {
          Name = "my-nacl"
        }
      }
      

      请注意,您可能需要在下面添加 egress 块:

        egress{
           protocol   = "tcp"
            rule_no    = 300
            action     = "allow"
            cidr_block = "0.0.0.0/0"
            from_port  = 1024
            to_port    = 65535
        }
      

      如上所述here

      要启用与实例上运行的服务的连接, 关联的网络 ACL 必须允许端口上的入站流量 该服务正在侦听并允许出站流量 从临时端口。当客户端连接到服务器时,随机 临时端口范围(1024-65535)中的端口成为客户端的 源端口。

      【讨论】:

        猜你喜欢
        • 2022-11-16
        • 1970-01-01
        • 1970-01-01
        • 2021-04-21
        • 2017-07-25
        • 1970-01-01
        • 1970-01-01
        • 2021-03-09
        • 2019-10-25
        相关资源
        最近更新 更多