开放策略代理 - 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 映射到 resultpolicy_name2result2。我们称这种规则为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 管道中的显式逻辑与的主要内容,如果未能解决你的问题,请参考以下文章

什么是Selenium Webdriver中的显式等待与隐式等待?

开放策略代理 - 错误与无

高级系统架构师必知的经纪人Broker设计

运算符重载中的显式构造?

Scala 中的显式类型转换

Swift 2 中的显式老式错误处理