Terraform(AWS)使用循环逻辑动态创建私有ACL

时间:2020-07-08 16:11:57

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

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

public_acl_rule的Terraform块:

--spring.config.location

我尝试了下面的aws_network_acl和内联块来遍历public_cidr块:

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)

}

cidr_block正在请求对private_inbound_acl_rule的引用,如计数中提到的那样。

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

2 个答案:

答案 0 :(得分:0)

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

  1. 要遍历公共cidr_block范围以为专用子网创建NACL规则。

  2. 要在ssh规则有效时动态获取输入,需要启用数据库连接并根据条件创建规则。

我通过以下代码实现了相同的目的:

## 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
}

答案 1 :(得分:0)

从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)中的端口成为客户端的 源端口。