【问题标题】:Running Terraform on AWS without VPC endpoints or 0.0.0.0/0 rules在没有 VPC 端点或 0.0.0.0/0 规则的 AWS 上运行 Terraform
【发布时间】:2020-03-10 17:59:22
【问题描述】:

我有一个 EC2 实例,我将在该实例上运行 Terraform 以在 AWS 中预置一堆其他资源。我不想让这台服务器出站互联网访问,因为它唯一需要访问的是 AWS API,所以我走的是 VPC 端点路由。

在我需要配置有 no VPC endpoint 的资源(例如 RDS 和 Elasticache)之前,这一直很好。我不想让这个实例访问互联网并在端口 443 上创建出站 0.0.0.0/0 规则,但我看不到其他方式。

有没有办法限制仅对 AWS API 的出站 HTTPS 访问?

【问题讨论】:

  • 我假设您已经考虑过 Terraform 通常需要与之通信的其他事物?例如,从注册表中获取提供程序插件等。这是一个有趣的问题,我想我有一个合理的答案,但可能会花一点时间玩弄一些东西,所以可能需要等到明天才能完全回答。

标签: amazon-web-services terraform terraform-provider-aws


【解决方案1】:

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"]
}

以上示例将获取您正在运行的区域的 AMAZONEC2 块(它们是 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

每个安全组可以有 60 个入站规则和 60 个出站规则 (总共制定了 120 条规则)。此配额单独执行 IPv4规则和IPv6规则;例如,一个安全组可以有 60 IPv4 流量的入站规则和 IPv6 流量的 60 个入站规则。 引用安全组或前缀列表 ID 的规则算作 IPv4 一条规则,IPv6 一条规则。

配额更改适用于入站和出站规则。这个配额 乘以每个网络接口的安全组配额 不能超过 1000。例如,如果您将此配额增加到 100,我们 减少每个网络的安全组数量的配额 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
}

【讨论】:

    猜你喜欢
    • 2017-06-02
    • 2023-02-07
    • 1970-01-01
    • 2022-11-16
    • 2021-11-01
    • 2020-02-17
    • 2021-10-31
    • 2022-11-15
    • 2019-08-29
    相关资源
    最近更新 更多