如何将输入传递给定义集合文档的查询规则

How to pass input to query rule defining a set document

在OPA的文档中有很多生成sets/arrays/objects用于查询的例子,例如:

app_to_hostnames[app_name] = hostnames {
    app := apps[_]
    app_name := app.name
    hostnames := [hostname | name := app.servers[_]
                            s := sites[_].servers[_]
                            s.name == name
                            hostname := s.hostname]
}

但是,在文档中,所有数据都是静态定义的:在示例中,变量 apps 已经存在并且被定义为某个 json 对象。

为了可重用性,我想定义一个 returns 和 set/array/object 但允许动态传递输入的函数。本质上我想尝试做的是以下内容:

app_to_hostnames[app_name](apps) = hostnames {
    app := apps[_]
    app_name := app.name
    hostnames := [hostname | name := app.servers[_]
                            s := sites[_].servers[_]
                            s.name == name
                            hostname := s.hostname]
}

在这种情况下,应用程序作为函数输入传递。有没有办法在 Rego 政策中实现这一目标?或者我应该以不同的方式处理这个问题?或者有没有办法将不同的输入传递给不同的策略?

我知道您可以通过 REST API 将输入发送到特定策略并以这种方式控制它,但在这种情况下,我使用 conftest 来传递输入文档(例如json 文件)到一组已编译的 rego 策略),因此使用 REST API 对我不起作用。

inputdata 文档是全局的。您始终可以使用 with 关键字在给定表达式上替换它们的值,但有时将逻辑包装在函数中更自然。

可以使用理解重写该具体示例:

app_to_hostnames(apps, sites) = {app_name: hostnames |
    app := apps[_]
    app_name := app.name
    hostnames := [hostname | name := app.servers[_]
                            s := sites[_].servers[_]
                            s.name == name
                            hostname := s.hostname]
}

或者,您可以使用 with 关键字临时替换 datainput 文档的部分内容。例如,如果 appssites 是从包含 app_to_hostnames 的文件中的数据下导入的,您可以按如下方式查询 app_to_hostnames

mock_apps := [
  {"name": "foo", "servers": ["s1"]},
  {"name": "bar", "servers": ["s2", "s3"]},
]

mock_sites := [
  {"servers": [{"name": "s1", "hostname": "x.com"}]},
  {"servers": [{"name": "s2", "hostname": "y.com"}, {"name": "s3", "hostname": "z.com"}]},
]

app_to_hostnames == {"foo": ["x.com"], "bar": ["y.com", "z.com"]} with data.apps as mock_apps with data.sites as mock_sites

这里有一个 link 游乐场内的政策:https://play.openpolicyagent.org/p/pEp6BLCtgn