amazon-web-services - 尝试使用 Terraform 创建 AWS VPC 安全组时出现循环错误

标签 amazon-web-services amazon-vpc terraform

我想创建 2 个 VPC 安全组。

一个用于 VPC 的堡垒主机,一个用于私有(private)子网。

# BASTION # 
resource "aws_security_group" "VPC-BastionSG" {
  name        = "VPC-BastionSG"
  description = "The sec group for the Bastion instance"
  vpc_id      = "aws_vpc.VPC.id"

  ingress {
      from_port = 22
      to_port   = 22
      protocol  = "tcp"
      cidr_blocks = ["my.super.ip/32"]
  } 

  egress {
      # Access to the Private subnet from the bastion host[ssh]
      from_port = 22
      to_port   = 22
      protocol  = "tcp"
      security_groups = ["${aws_security_group.VPC-PrivateSG.id}"]
  }
  egress {
      # Access to the Private subnet from the bastion host[jenkins]
      from_port = 8686
      to_port   = 8686
      protocol  = "tcp"
      security_groups = ["${aws_security_group.VPC-PrivateSG.id}"]
  }

  tags = {
    Name = "VPC-BastionSG"
  }
}

# PRIVATE #
resource "aws_security_group" "VPC-PrivateSG" {
  name        = "VPC-PrivateSG"
  description = "The sec group for the private subnet"
  vpc_id      = "aws_vpc.VPC.id"

  ingress {
      from_port = 22
      to_port   = 22
      protocol  = "tcp"
      security_groups = ["${aws_security_group.VPC-BastionSG.id}"]
  }
  ingress {
      from_port = 80
      to_port   = 80
      protocol  = "tcp"
      security_groups = ["${aws_security_group.VPC-PublicSG.id}"]
  }
  ingress {
      from_port = 443
      to_port   = 443
      protocol  = "tcp"
      security_groups = ["${aws_security_group.VPC-PublicSG.id}"]
  }
  ingress {
      from_port = 3306
      to_port   = 3306
      protocol  = "tcp"
      security_groups = ["${aws_security_group.VPC-PublicSG.id}"]
  }
  ingress {
      from_port = 8686
      to_port   = 8686
      protocol  = "tcp"
      security_groups = ["${aws_security_group.VPC-BastionSG.id}"]
  }
  ingress {
      # ALL TRAFFIC from the same subnet
      from_port = 0
      to_port   = 0
      protocol  = "-1"
      self      = true
  }
  egress {
      # ALL TRAFFIC to outside world
      from_port = 0
      to_port   = 0
      protocol  = "-1"
      cidr_blocks = ["0.0.0.0/0"]
  }
  tags = {
    Name = "VPC-PrivateSG"
  }
}

当我terraform plan它,返回此错误:
**`Error configuring: 1 error(s) occurred:
* Cycle: aws_security_group.VPC-BastionSG, aws_security_group.VPC-PrivateSG`**

如果我从 PrivateSG 中注释掉 BastionSG 的入口规则,则该计划执行得很好。

此外,如果我从 BastionSG 中注释掉 PrivateSG 的导出规则,它也可以正常执行。

AWS Scenario 2 for building a VPC with Public/Private subnets and Bastion host描述了我正在尝试设置的架构。

我通过 AWS 控制台配置了完全相同的设置,并且运行良好。

为什么 Terraform 不接受它?
还有其他方法可以将 Bastion 安全组与 Private 安全组连接起来吗?

编辑

据我了解,两个 sec 组之间存在一个循环引用,即使在 AWS 中它是有效的,它也需要以某种方式中断。

因此,我考虑允许来自 Bastion sec 组的所有出站流量 (0.0.0.0/0),而不是将其指定给各个安全组。

会不会对安全造成不良影响?

最佳答案

Terraform 尝试为它正在处理的文件夹中定义的所有资源构建依赖链。这样做可以使其确定是否需要以特定顺序构建事物,并且对于它如何工作非常关键。
您的示例将失败,因为您有一个循环依赖(正如 Terraform 有用地指出的那样),其中每个安全组都依赖于已经创建的另一个。
有时这些可能很难解决,并且可能意味着您需要重新考虑您正在尝试做什么(正如您所提到的,一种选择是简单地允许所有导出流量从堡垒主机流出,并且只限制私有(private)上的入口流量实例),但在这种情况下,您可以选择使用 aws_security_group_rule 资源结合 aws_security_group 资源。
这意味着我们可以首先定义其中没有规则的空安全组,然后我们可以将其用作我们为这些组创建的安全组规则的目标。
一个简单的示例可能如下所示:

resource "aws_security_group" "bastion" {
  name = "bastion"
  description = "Bastion security group"
}

resource "aws_security_group_rule" "bastion-to-private-ssh-egress" {
    type = "egress"
    from_port = 22
    to_port = 22
    protocol = "tcp"
    security_group_id = "${aws_security_group.bastion.id}"
    source_security_group_id = "${aws_security_group.private.id}"
}

resource "aws_security_group" "private" {
  name = "private"
  description = "Private security group"
}

resource "aws_security_group_rule" "private-from-bastion-ssh-ingress" {
    type = "ingress"
    from_port = 22
    to_port = 22
    protocol = "tcp"
    security_group_id = "${aws_security_group.private.id}"
    source_security_group_id = "${aws_security_group.bastion.id}"
}
现在,Terraform 可以看到依赖链表明必须在其中任何一个安全组规则之前创建两个安全组,因为它们都依赖于已经创建的组。

关于amazon-web-services - 尝试使用 Terraform 创建 AWS VPC 安全组时出现循环错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38246326/

相关文章:

amazon-web-services - 覆盖cloudformation参数文件中的参数

amazon-web-services - 位于独立 Kubernetes 集群中的两个 Pod 之间的连接

amazon-web-services - 在用于创建 RabbitMQ 集群的 AWS VPC 中找不到节点?

azure - 从 terraform 脚本为 Azure Active Directory 打开 'App Service Authentication'

amazon-web-services - aws_acm_certificate 似乎已经改变了它的状态输出,可能是由于提供者更新——我做错了吗?

node.js - 从 s3 获取签名的 url 以使用 SSE-C 解密上传的对象

amazon-web-services - AWS 使用 Fargate 对 ECS 服务的多个端口进行负载平衡

database - 如何使用云形成 yaml 配置设置 DynamoDB 的最大预配置容量?

amazon-web-services - Amazon VPC 到 VPC 连接

azure - Terraform Azurerm 抛出此处不需要名为 "java_version"的参数