使用 Rego 根据另一个列表验证列表的每个元素
Validating every element of a list against another list using Rego
我是 rego 的新手,我正在尝试编写一个策略来根据另一个列表验证一个列表的元素。这是我要解决的问题:
我有一个已批准的安全组列表,我需要根据我的输入检查安全组。如果我输入的 SG 不是来自批准的列表,我需要输出一条消息“正在使用无效的 SG”。
我找不到任何说明如何将一个列表与另一个列表进行比较的文档。
这是 rego playground 中的政策:https://play.openpolicyagent.org/p/m09f2K1g0h
政策:
check_list = ["sg-1001a1d199tx8866a","sg-2002b2e200in9966b", "sg-3003c3f201dc0011c","sg-4004d4e202nj1122d", "sg-5003c3f201dc0011e","sg-6004d4e202nj1122f"]
aws_valid_sgs := {i: Reason |
doc = input[i]; i="aws_launch_configuration.ecs-cluster-lc"
key_ids := [k | doc[k]; startswith(k, "security_groups.")]
resource := {
doc[k] : doc[replace(k, ".key", ".value")] | key_ids[_] == k
}
sg_ids := [m | resource[m]; startswith(m, "sg-")]
list := {x| x:=check_list[_]}
not(list[sg_ids[i]])
Reason := sprintf("Resource %v is not using an approved SG ", [doc.name])
}
输入:
{
"aws_launch_configuration.ecs-cluster-lc": {
"associate_public_ip_address": "false",
"destroy": false,
"destroy_tainted": false,
"ebs_block_device.#": "",
"ebs_optimized": "",
"enable_monitoring": "true",
"id": "",
"instance_type": "t3.large",
"key_name": "",
"name": "test_r1-us-east-1",
"security_groups.1122334455": "sg-1001a1d199tx8866a",
"security_groups.2233445566": "sg-2002b2e200in9966b",
"security_groups.3344556677": "sg-3003c3f201dc0011c",
"security_groups.4455667788": "sg-4004d4e202nj1122d"
},
"destroy": false
}
感谢任何帮助。谢谢
TLDR;这最好使用 set 操作来完成,例如 {"foo", "bar", "baz"} - {"bar"} == {"foo", "baz"}
)。这是一个完整的例子:
# Define a SET of valid SGs to compare against.
valid_sgs := {"sg-1001a1d199tx8866a","sg-2002b2e200in9966b", "sg-3003c3f201dc0011c","sg-4004d4e202nj1122d", "sg-5003c3f201dc0011e","sg-6004d4e202nj1122f"}
# Compute the SET of SGs from the launch configuration in the input.
launch_config_sgs := {sg |
some key
launch_config := input["aws_launch_configuration.ecs-cluster-lc"]
sg := launch_config[key]
startswith(key, "security_groups.")
}
# Compute the SET of invalid SGs by taking the difference of the other two sets.
invalid_launch_config_sgs := launch_config_sgs - valid_sgs
# Generate a 'deny' message if there are any invalid SGs.
deny[msg] {
launch_config := input["aws_launch_configuration.ecs-cluster-lc"]
count(invalid_launch_config_sgs) > 0
msg := sprintf("Resource %v is not using an approved SG", [launch_config.name])
}
海报版本中有一些东西使问题变得比必要的更难:
check_list
被定义为一个 数组 (不是集合)。数组按位置索引。要检查某个值是否包含在列表中,您需要迭代。构建集合并测试 membership/intersection/difference/etc.
通常更容易
aws_valid_sgs
规则从输入中构造了一堆不必要的中间值(例如,doc
、key_ids
、resource
等。 ) 所需要的只是来自输入的一组 SG,可以在 2 个语句中计算:在启动配置中查找键以 security_group.
开头的字段,并为这些键构建一组字段值。
我是 rego 的新手,我正在尝试编写一个策略来根据另一个列表验证一个列表的元素。这是我要解决的问题: 我有一个已批准的安全组列表,我需要根据我的输入检查安全组。如果我输入的 SG 不是来自批准的列表,我需要输出一条消息“正在使用无效的 SG”。 我找不到任何说明如何将一个列表与另一个列表进行比较的文档。 这是 rego playground 中的政策:https://play.openpolicyagent.org/p/m09f2K1g0h
政策:
check_list = ["sg-1001a1d199tx8866a","sg-2002b2e200in9966b", "sg-3003c3f201dc0011c","sg-4004d4e202nj1122d", "sg-5003c3f201dc0011e","sg-6004d4e202nj1122f"]
aws_valid_sgs := {i: Reason |
doc = input[i]; i="aws_launch_configuration.ecs-cluster-lc"
key_ids := [k | doc[k]; startswith(k, "security_groups.")]
resource := {
doc[k] : doc[replace(k, ".key", ".value")] | key_ids[_] == k
}
sg_ids := [m | resource[m]; startswith(m, "sg-")]
list := {x| x:=check_list[_]}
not(list[sg_ids[i]])
Reason := sprintf("Resource %v is not using an approved SG ", [doc.name])
}
输入:
{
"aws_launch_configuration.ecs-cluster-lc": {
"associate_public_ip_address": "false",
"destroy": false,
"destroy_tainted": false,
"ebs_block_device.#": "",
"ebs_optimized": "",
"enable_monitoring": "true",
"id": "",
"instance_type": "t3.large",
"key_name": "",
"name": "test_r1-us-east-1",
"security_groups.1122334455": "sg-1001a1d199tx8866a",
"security_groups.2233445566": "sg-2002b2e200in9966b",
"security_groups.3344556677": "sg-3003c3f201dc0011c",
"security_groups.4455667788": "sg-4004d4e202nj1122d"
},
"destroy": false
}
感谢任何帮助。谢谢
TLDR;这最好使用 set 操作来完成,例如 {"foo", "bar", "baz"} - {"bar"} == {"foo", "baz"}
)。这是一个完整的例子:
# Define a SET of valid SGs to compare against.
valid_sgs := {"sg-1001a1d199tx8866a","sg-2002b2e200in9966b", "sg-3003c3f201dc0011c","sg-4004d4e202nj1122d", "sg-5003c3f201dc0011e","sg-6004d4e202nj1122f"}
# Compute the SET of SGs from the launch configuration in the input.
launch_config_sgs := {sg |
some key
launch_config := input["aws_launch_configuration.ecs-cluster-lc"]
sg := launch_config[key]
startswith(key, "security_groups.")
}
# Compute the SET of invalid SGs by taking the difference of the other two sets.
invalid_launch_config_sgs := launch_config_sgs - valid_sgs
# Generate a 'deny' message if there are any invalid SGs.
deny[msg] {
launch_config := input["aws_launch_configuration.ecs-cluster-lc"]
count(invalid_launch_config_sgs) > 0
msg := sprintf("Resource %v is not using an approved SG", [launch_config.name])
}
海报版本中有一些东西使问题变得比必要的更难:
通常更容易check_list
被定义为一个 数组 (不是集合)。数组按位置索引。要检查某个值是否包含在列表中,您需要迭代。构建集合并测试 membership/intersection/difference/etc.aws_valid_sgs
规则从输入中构造了一堆不必要的中间值(例如,doc
、key_ids
、resource
等。 ) 所需要的只是来自输入的一组 SG,可以在 2 个语句中计算:在启动配置中查找键以security_group.
开头的字段,并为这些键构建一组字段值。