我想创建 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/