我正在尝试编写一项管理管理员用户名兼容性的策略,该策略包含三个规则:字母数字值,不属于禁止名称(管理员,管理员等)的一部分以及超过5个字符。
我发现,将OPA用作CI管道的一部分(这是我的用例)时,最舒适的解决方案是创建一个包含策略结果的对象(字典),以便我可以直接查询它们。我在CI管道中的行将如下所示:
for file in rego_directory:
opa eval -i file -d data.json "package_name.policy"
不会打印出我在rego文件中使用的所有变量和临时资源(这会节省很多日志和输出)。为了制作这个“策略”对象,我在rego文件中添加了以下模式:
policy[policy_name] = result {
policy_name :=
...
computations...
...
result := <logical condition>
}
现在,我的问题如下:对我来说,这似乎不是最佳实践。还有另一种方法可以简单地忽略输出中的变量吗?以前我曾使用过单独的值(即类似这样的值:
default policy_1 = false
default policy_2 = false
policy_1 = {
<logical condition>
}
policy_2 = {
<logical condition>
}
第二个问题:如何创建可以满足多个条件的输出字典(毕竟字典的JSON输出是一种不错的格式)?回顾我的示例,我不能写这样的东西:
policy[policy_name] = result {
policy_name :=
...
computations...
...
result := <logical condition>
result := <logical condition 2>
}
因为这是双重分配,所以无效。即使我使用=
而不是:=
,如果一个术语为true,另一个术语为false,它也会产生冲突,并且错误不是我想要的(我需要布尔值答案)。如何创建一个复杂的规则,可以将其输出放入此词典中?
谢谢。
答案 0 :(得分:1)
TLDR;明确回答您的问题:
现在,我的问题如下:对我来说,这似乎不是最佳实践。还有另一种方法可以简单地忽略输出中的变量吗?
让您的软件查询某些规则生成的值没有错。实际上,规则是在策略中定义抽象的基本方式,因此您可以将策略决策(即产生决策的逻辑)与策略执行(即基于策略决策采取的逻辑/动作)分离。 )
唯一真实的选择是在一个或多个如您所示的包中查询一组规则。
第二个问题:如何创建可以满足多个条件的输出字典(毕竟字典的JSON输出是一种不错的格式)?回顾我的示例,我不能写这样的东西:
您在问如何表达Logical OR。在这种情况下,您将创建policy
规则的多个定义(在某些地方称为“增量定义”):
policy[policy_name] = result {
policy_name :=
...
computations...
...
result := <logical condition>
}
policy[policy_name2] = result2 {
policy_name2 :=
...
some other computations...
...
result2 := <some other logical condition>
}
此代码段定义了一个对象(名为policy
),该对象将policy_name
映射到result
,并且将policy_name2
映射到result2
。我们称这种规则为Partial Object。您还可以定义部分集。定义部分对象时,需要确保每个键都映射到最多一个值(否则会出现运行时错误。)
构造策略的另一种方法是(本质上)使用部分集定义拒绝列表:
package usernames
deny["username must use alphanumeric characters"] {
re_match("[a-zA-Z0-9]", input.username)
}
deny["username must be at least 5 characters long"] {
count(input.username) < 5
}
deny["username is reserved"] {
reserved_usernames[input.username]
}
reserved_usernames := {"admin", "root"}
然后,您的CI管道可以简单地查询deny
:
opa eval -i input.json 'data.usernames.deny'
结果将包含为什么不允许使用用户名的原因。