开放策略代理 - CI 管道中的显式逻辑与
Posted
技术标签:
【中文标题】开放策略代理 - CI 管道中的显式逻辑与【英文标题】:Open policy agent - explicit logical AND in CI pipeline 【发布时间】:2020-07-07 11:56:02 【问题描述】:我正在尝试编写一个管理管理员用户名兼容性的策略,该策略由三个规则组成:字母数字值、不属于不允许的名称(管理员、管理员等)以及长度超过 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>
由于这是双重赋值,这是无效的。即使我使用=
而不是:=
,如果一个术语为真而另一个为假,它也会产生冲突,并且错误不是我要寻找的(我需要布尔答案)。如何创建一个复杂的规则,我可以把它的输出放到这个字典里?
提前致谢。
【问题讨论】:
【参考方案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>
这个 sn-p 定义了一个对象(名为 policy
),它将 policy_name
映射到 result
和 policy_name2
到 result2
。我们称这种规则为Partial Object。您还可以定义部分集。定义 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'
结果将包含不应允许该用户名的原因。
【讨论】:
您好,感谢您的回复!第一个答案对我来说很有意义。但是,关于我的第二个问题 - 我明确写道,我正在寻找逻辑 OR,因为我正在寻找我的 JSON 中的单个元素,该元素将具有布尔值。我想没有办法避免创建“帮助”政策,并且有一个政策是所有政策的与(A == true,B == true,C == true) 有点不清楚您在寻找什么作为策略/OPA 的响应。我假设你想要一个像 "p1": true/false, "p2": true/false, ... 这样的响应。例如,每个策略的键和每个策略的真/假值。如果您只需要一个布尔值,那么我的答案会有所改变。将策略分解成小块的“辅助”规则是一件好事——它使整体策略更具可读性。以上是关于开放策略代理 - CI 管道中的显式逻辑与的主要内容,如果未能解决你的问题,请参考以下文章