运行 AWS 上的 Terraform 没有 VPC 端点或 0.0.0.0/0 规则
Running Terraform on AWS without VPC endpoints or 0.0.0.0/0 rules
我有一个 EC2 实例,我将在其上 运行 Terraform 在 AWS 中配置大量其他资源。我不想为该服务器提供出站互联网访问权限,因为它唯一需要访问的是 AWS API,所以我沿着 VPC 端点路径走下去。
在我需要为有 no VPC endpoint 的资源(例如 RDS 和 Elasticache)配置资源之前,它一直运行良好。我不想为该实例提供互联网访问权限并在端口 443 上创建出站 0.0.0.0/0 规则,但我看不到其他方式。
有没有办法限制仅对 AWS API 进行出站 HTTPS 访问?
AWS 提供 a guide 用于计算任何服务端点的 IP 地址以允许出口到它。这依赖于下载所有 AWS 端点的 IP 地址,然后过滤 AMAZON
列表中的 IP 地址,但从 EC2
列表中删除那些。
谢天谢地,我们可以使用 aws_ip_ranges
data source 在 Terraform 中直接获取这些 IP 地址,并且可以过滤 AMAZON
范围和 EC2
范围:
data "aws_region" "current" {}
data "aws_ip_ranges" "amazon" {
regions = [data.aws_region.current.name]
services = ["amazon"]
}
data "aws_ip_ranges" "ec2" {
regions = [data.aws_region.current.name]
services = ["ec2"]
}
以上示例将获取您所在区域的 AMAZON
和 EC2
块(它们是 AMAZON
块的子集)的所有 IP 地址 运行英寸
要从 AMAZON
块中删除 EC2
块,我们需要使用 setsubtract
function:
locals {
aws_control_plane = setsubtract(data.aws_ip_ranges.amazon.cidr_blocks, data.aws_ip_ranges.ec2.cidr_blocks)
}
这应该只给我们想要允许我们的安全组出口的 IP 范围。
不幸的是,这可能超过 60 个 CIDR 范围,相当于超过 60 个规则。安全组是 limited to a max of 60 ingress and 60 egress rules:
You can have 60 inbound and 60 outbound rules per security group
(making a total of 120 rules). This quota is enforced separately for
IPv4 rules and IPv6 rules; for example, a security group can have 60
inbound rules for IPv4 traffic and 60 inbound rules for IPv6 traffic.
A rule that references a security group or prefix list ID counts as
one rule for IPv4 and one rule for IPv6.
A quota change applies to both inbound and outbound rules. This quota
multiplied by the quota for security groups per network interface
cannot exceed 1000. For example, if you increase this quota to 100, we
decrease the quota for your number of security groups per network
interface to 10.
但是,我们可以为每个接口设置多个安全组,这样我们就可以将这些范围分布在多个安全组中,并将多个安全组附加到实例:
为此,我们需要将我们拥有的范围列表分成 60 个块,然后遍历我们将要创建的安全组资源。我们可以用 chunklist
function:
locals {
aws_control_plane_chunked = chunklist(local.aws_control_plane, 60)
}
这是一个列表列表,每个列表最多包含 60 个 CIDR 块。
然后我们可以通过遍历这些列表来创建我们的多个安全组:
resource "aws_security_group" "aws_only_egress" {
count = length(local.aws_control_plane_chunked)
name = "aws-only-egress-example-chunk-${count.index + 1}"
egress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = local.aws_control_plane_chunked[count.index]
}
}
然后最后我们需要将这些多个安全组附加到我们的实例:
data "aws_ami" "ubuntu" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["099720109477"] # Canonical
}
resource "aws_instance" "example" {
ami = data.aws_ami.ubuntu.id
instance_type = "t3.micro"
vpc_security_group_ids = aws_security_group.aws_only_egress.*.id
}
我有一个 EC2 实例,我将在其上 运行 Terraform 在 AWS 中配置大量其他资源。我不想为该服务器提供出站互联网访问权限,因为它唯一需要访问的是 AWS API,所以我沿着 VPC 端点路径走下去。
在我需要为有 no VPC endpoint 的资源(例如 RDS 和 Elasticache)配置资源之前,它一直运行良好。我不想为该实例提供互联网访问权限并在端口 443 上创建出站 0.0.0.0/0 规则,但我看不到其他方式。
有没有办法限制仅对 AWS API 进行出站 HTTPS 访问?
AWS 提供 a guide 用于计算任何服务端点的 IP 地址以允许出口到它。这依赖于下载所有 AWS 端点的 IP 地址,然后过滤 AMAZON
列表中的 IP 地址,但从 EC2
列表中删除那些。
谢天谢地,我们可以使用 aws_ip_ranges
data source 在 Terraform 中直接获取这些 IP 地址,并且可以过滤 AMAZON
范围和 EC2
范围:
data "aws_region" "current" {}
data "aws_ip_ranges" "amazon" {
regions = [data.aws_region.current.name]
services = ["amazon"]
}
data "aws_ip_ranges" "ec2" {
regions = [data.aws_region.current.name]
services = ["ec2"]
}
以上示例将获取您所在区域的 AMAZON
和 EC2
块(它们是 AMAZON
块的子集)的所有 IP 地址 运行英寸
要从 AMAZON
块中删除 EC2
块,我们需要使用 setsubtract
function:
locals {
aws_control_plane = setsubtract(data.aws_ip_ranges.amazon.cidr_blocks, data.aws_ip_ranges.ec2.cidr_blocks)
}
这应该只给我们想要允许我们的安全组出口的 IP 范围。
不幸的是,这可能超过 60 个 CIDR 范围,相当于超过 60 个规则。安全组是 limited to a max of 60 ingress and 60 egress rules:
You can have 60 inbound and 60 outbound rules per security group (making a total of 120 rules). This quota is enforced separately for IPv4 rules and IPv6 rules; for example, a security group can have 60 inbound rules for IPv4 traffic and 60 inbound rules for IPv6 traffic. A rule that references a security group or prefix list ID counts as one rule for IPv4 and one rule for IPv6.
A quota change applies to both inbound and outbound rules. This quota multiplied by the quota for security groups per network interface cannot exceed 1000. For example, if you increase this quota to 100, we decrease the quota for your number of security groups per network interface to 10.
但是,我们可以为每个接口设置多个安全组,这样我们就可以将这些范围分布在多个安全组中,并将多个安全组附加到实例:
为此,我们需要将我们拥有的范围列表分成 60 个块,然后遍历我们将要创建的安全组资源。我们可以用 chunklist
function:
locals {
aws_control_plane_chunked = chunklist(local.aws_control_plane, 60)
}
这是一个列表列表,每个列表最多包含 60 个 CIDR 块。
然后我们可以通过遍历这些列表来创建我们的多个安全组:
resource "aws_security_group" "aws_only_egress" {
count = length(local.aws_control_plane_chunked)
name = "aws-only-egress-example-chunk-${count.index + 1}"
egress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = local.aws_control_plane_chunked[count.index]
}
}
然后最后我们需要将这些多个安全组附加到我们的实例:
data "aws_ami" "ubuntu" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["099720109477"] # Canonical
}
resource "aws_instance" "example" {
ami = data.aws_ami.ubuntu.id
instance_type = "t3.micro"
vpc_security_group_ids = aws_security_group.aws_only_egress.*.id
}