使用 JQ 将字符串数组转换为字典?



我尝试将 AWS 公有IP 范围转换为可与 Terraformexternal数据提供程序一起使用的格式,以便我可以基于 AWS 公有 CIDR 创建安全组规则。提供程序需要具有以下格式的单个 JSON 对象:

{"string": "string"}

以下是公共范围 JSON 文档的片段:

{
"syncToken": "1589917992",
"createDate": "2020-05-19-19-53-12",
"prefixes": [
{
"ip_prefix": "35.180.0.0/16",
"region": "eu-west-3",
"service": "AMAZON",
"network_border_group": "eu-west-3"
},
{
"ip_prefix": "52.94.76.0/22",
"region": "us-west-2",
"service": "AMAZON",
"network_border_group": "us-west-2"
},
// ...
]

我可以成功地提取我关心的范围,[.prefixes[] | select(.region == "us-west-2") | .ip_prefix] | sort | unique,它给了我这个:

[
"100.20.0.0/14",
"108.166.224.0/21",
"108.166.240.0/21",
"13.248.112.0/24",
...
]

我不知道如何使用 jq 将其转换为任意键控的对象。为了正确使用数组对象,我需要将其转换为字典,例如{"arbitrary-key": "100.20.0.0/14"},以便我可以像这样在 Terraform 中使用它:

data "external" "amazon-ranges" {
program = [
"cat",
"${path.cwd}/aws-ranges.json"
]
}
resource "aws_default_security_group" "allow-mysql" {
vpc_id = aws_vpc.main.id
ingress {
description = "MySQL"
from_port   = 0
to_port     = 0
protocol    = "-1"
cidr_blocks = [
values(data.external.amazon-ranges.result)
]
}
}

将 AWS 公有 IP 范围文档提取到具有任意键的单个对象中的最有效方法是什么?

以下脚本使用.ip_prefix作为键,因此可能避免了对sort|unique的需要。 它产生:

{
"35.180.0.0/16": "35.180.0.0/16",
"52.94.76.0/22": "52.94.76.0/22"
}

脚本

#!/bin/bash
function data {
cat <<EOF
{
"syncToken": "1589917992",
"createDate": "2020-05-19-19-53-12",
"prefixes": [
{
"ip_prefix": "35.180.0.0/16",
"region": "eu-west-3",
"service": "AMAZON",
"network_border_group": "eu-west-3"
},
{
"ip_prefix": "52.94.76.0/22",
"region": "us-west-2",
"service": "AMAZON",
"network_border_group": "us-west-2"
}
]
}
EOF
}
data | jq '
.prefixes 
| map(select(.region | test("west"))
| {(.ip_prefix): .ip_prefix} )
| add '

在Terraform 中获取 AWS IP 范围数据有一个更好的选择,即使用aws_ip_ranges数据源,而不是尝试使用external数据源和jq进行混乱。

上面链接文档中的示例显示了与您在此处尝试执行的操作类似但稍微复杂的事情:

data "aws_ip_ranges" "european_ec2" {
regions  = ["eu-west-1", "eu-central-1"]
services = ["ec2"]
}
resource "aws_security_group" "from_europe" {
name = "from_europe"
ingress {
from_port        = "443"
to_port          = "443"
protocol         = "tcp"
cidr_blocks      = data.aws_ip_ranges.european_ec2.cidr_blocks
ipv6_cidr_blocks = data.aws_ip_ranges.european_ec2.ipv6_cidr_blocks
}
tags = {
CreateDate = data.aws_ip_ranges.european_ec2.create_date
SyncToken  = data.aws_ip_ranges.european_ec2.sync_token
}
}

要做你的确切事情,你会做这样的事情:

data "aws_ip_ranges" "us_west_2_amazon" {
regions  = ["us_west_2"]
services = ["amazon"]
}
resource "aws_default_security_group" "allow-mysql" {
vpc_id = aws_vpc.main.id
ingress {
description = "MySQL"
from_port   = 0
to_port     = 0
protocol    = "-1"
cidr_blocks = data.aws_ip_ranges.us_west_2_amazon.cidr_blocks
}
}

但是,这里有两件事不好。

首先,也是最重要的一点是,您允许从 AWS 在所有服务中拥有的 US-West-2 中的每个 IP 地址访问您的数据库。这意味着世界上任何人都可以在 US-West-2 中启动 EC2 实例或 Lambda 函数,然后通过网络访问您的数据库。这是一个非常糟糕的主意。

第二个是,如果返回超过 60 个 CIDR 块,则安全组中最终将包含 60 多个规则。AWS 安全组对每个 IP 地址类型(IPv4 与 IPv6(和每个入口/出口限制为 60 个安全组规则:

每个安全组可以有 60 个入站规则和 60 个出站规则(总共 120 条规则(。此配额分别针对 IPv4 规则和 IPv6 规则强制实施;例如,安全组可以有 60 个 IPv4 流量入站规则和 60 个 IPv6 流量入站规则。引用安全组或前缀列表 ID 的规则计为 IPv4 的一个规则和一个 IPv6 规则。

从 https://docs.aws.amazon.com/vpc/latest/userguide/amazon-vpc-limits.html#vpc-limits-security-groups

从技术上讲,这是一个软上限,您可以要求 AWS 提高此限制,以换取减少可应用于网络接口的安全组数量,以将每个网络接口的最大安全组规则数量保持在 1000 或以下。不过,这可能不是你想乱搞的东西。

相关内容

  • 没有找到相关文章

最新更新