OPA 文档模型

OPA将从外部加载的数据成为基本文档(base documents),有规则产生的值成为虚拟文档(virtual documents),此处"虚拟"的意思表示文档由策略进行了计算,且不是外部加载的。Rego中可以使用名为data的全局变量访问这两种数据。

异步加载的基本文档可以通过data全局变量进行访问。另一方面,如果软件需要查询OPA来获取策略决策时,也可以将基础文档同步推入或拉入OPA,此时需要通过input全局变量来引用同步推送的基本文档。同步加载的数据保存在data之外,防止命名冲突。

逻辑与

{
"servers": [
{"id": "app", "protocols": ["https", "ssh"], "ports": ["p1", "p2", "p3"]},
{"id": "db", "protocols": ["mysql"], "ports": ["p3"]},
{"id": "cache", "protocols": ["memcache"], "ports": ["p3"]},
{"id": "ci", "protocols": ["http"], "ports": ["p1", "p2"]},
{"id": "busybox", "protocols": ["telnet"], "ports": ["p1"]}
],
"networks": [
{"id": "net1", "public": false},
{"id": "net2", "public": false},
{"id": "net3", "public": true},
{"id": "net4", "public": true}
],
"ports": [
{"id": "p1", "network": "net1"},
{"id": "p2", "network": "net3"},
{"id": "p3", "network": "net2"}
]
}

OPA使用;来表示逻辑AND

input.servers[0].id == "app"; input.servers[0].protocols[0] == "https"

$ true

也可以使用多行来忽略;

input.servers[0].id == "app"
input.servers[0].protocols[0] == "https" $ rue

如果引用的内容不存在或匹配失败,则返回的结果为undefined

s := input.servers[0]
s.id == "app1" $undefined decision
s := input.servers[1110]

s.id == "app1"
$ undefined decision

变量

OPA的变量一旦赋值之后就是不可变的:

s := input.servers[0]
s := input.servers[1] $ 1 error occurred: 2:1: rego_compile_error: var s assigned above

迭代

找出连接到public网络的portsid,下面使用some关键字定义循环的变量,使用id变量提取符合要求的portsid,最后一行input.networks[j].public也可以写为input.networks[j].public==true,同时注意条件之间是逻辑与的关系

some i, j
id := input.ports[i].id
input.ports[i].network == input.networks[j].id
input.networks[j].public $ +---+------+---+
| i | id | j |
+---+------+---+
| 1 | "p2" | 2 |
+---+------+---+

可以使用下划线_(通配符)进行遍历,使用下划线来表示实例的单独变量。如使用如下方式找出input.servers中协议为httpid

s := input.servers[_]
id := s.id
s.protocols[_] == "http" $ true

规则(Rules)

使用规则可以重用判定逻辑,可以看作是一种函数实现。规则可以是"完整(complete)"或"部分(partial)"的。

完整规则

每个规则都包含一个head和一个body,如下headany_public_networks = truebodynet := input.networks[_]; net.public。如果忽略= <value>部分(= <value>用于使用右值赋予左边的变量,如apps_by_hostname[hostname] = app,key为hostname,value为app),则默认为true

package example.rules

any_public_networks = true {  # is true if...
net := input.networks[_] # some network exists and..
net.public # it is public.
}

可以为规则定义默认值,这样在结果返回"undefined decision"时,会将any_public_networks置为false

package example.rules

default any_public_networks = false
any_public_networks = true { # is true if...
net := input.no_exist_networks[_] # some network exists and..
net.public # it is public.
} any_public_networks $ false

可以使用如下方式进行访问:

any_public_networks

$ true

也可以使用全局变量data进行访问,访问方式为data.<package-path>.<rule-name>

data.example.rules.any_public_networks

$ true

可以使用如下方式定义常量

package example.constants

pi := 3.14

部分规则

headpublic_network[net.id]bodynet := input.networks[_]; net.public,可以看作是带返回值的函数

package example.rules

public_network[net.id] {      # net.id is in the public_network set if...
net := input.networks[_] # some network exists and...
net.public # it is public.
}

可以遍历返回值

public_network[_]

$ +-------------------+
| public_network[_] |
+-------------------+
| "net3" |
| "net4" |
+-------------------+

逻辑或

完整规则的逻辑或

使用逻辑或时,要求多条规则的名称相同。如下用于校验servers是否暴露了telnetssh协议:

package example.logical_or

default shell_accessible = false

shell_accessible = true {
input.servers[_].protocols[_] == "telnet"
} shell_accessible = true {
input.servers[_].protocols[_] == "ssh"
}
部分规则的逻辑或

如下规则用于找出协议为telnetssh的server的id

package example.logical_or

shell_accessible[server.id] {
server := input.servers[_]
server.protocols[_] == "telnet"
} shell_accessible[server.id] {
server := input.servers[_]
server.protocols[_] == "ssh"
}

rego语法

标量

rego支持字符串、数字、布尔和null

greeting   := "Hello"
max_height := 42
pi := 3.14159
allowed := true
location := null

字符串

支持两种类型的字符串:双引号包围的字符串和原始字符串,后者一般用于正则表达式。

复合值

定义了数值集合

cube := {"width": 3, "height": 4, "depth":true}
cube.depth

$ true

对象

可以看作golang的map

ips_by_port := {
80: ["1.1.1.1", "1.1.1.2"],
443: ["2.2.2.1"],
}
ips_by_port[80]

$ [
"1.1.1.1",
"1.1.1.2"
]

数组

数组使用下标进行索引

s1 := [1, 2, 3]
s2 := [2, 1, 3]
s1[1]
$ 2
s1 == s2
$ false

集合

它是唯一值的无序集合。它没有key,且无法使用下标进行索引。注意在解析为JSON格式时,集合体现为数组格式。

s1 := {1, 2, 3}
s2 := {2, 1, 3}
s1 == s2
$ true

变量

变量位于规则的head和body,规则head中的变量可以认为是输入或输出,如果提供了确定的值,则认为是输入,否则认为是输出。例如:

sites := [
{"name": "prod"},
{"name": "smoke1"},
{"name": "dev"}
] q[name] { name := sites[_].name }

如下x并没有绑定到某个值,则返回所有xq[x]的值

q[x]
$ +----------+----------+
| x | q[x] |
+----------+----------+
| "dev" | "dev" |
| "prod" | "prod" |
| "smoke1" | "smoke1" |
+----------+----------+

如下"dev"是一个确定的值,作为输入,用于判断name中是否存在该值

q["dev"]
$ "dev"

引用

有两种方式访问嵌套文档:点访问方式和方括号访问方式,如下:

sites[0].servers[1].hostname
sites[0]["servers"][1]["hostname"]

变量键

引用可以使用变量作为键,这种方式用于选择所有元素的值

sites[i].servers[j].hostname

$ +---+---+------------------------------+
| i | j | sites[i].servers[j].hostname |
+---+---+------------------------------+
| 0 | 0 | "hydrogen" |
| 0 | 1 | "helium" |
| 0 | 2 | "lithium" |
| 1 | 0 | "beryllium" |
| 1 | 1 | "boron" |
| 1 | 2 | "carbon" |
| 2 | 0 | "nitrogen" |
| 2 | 1 | "oxygen" |
+---+---+------------------------------+

如果迭代时不需要用到变量,则可以使用下划线_

sites[_].servers[_].hostname
$ +------------------------------+
| sites[_].servers[_].hostname |
+------------------------------+
| "hydrogen" |
| "helium" |
| "lithium" |
| "beryllium" |
| "boron" |
| "carbon" |
| "nitrogen" |
| "oxygen" |
+------------------------------+

复合键

s := {[1, 2], [1, 4], [2, 6]}
s[[1, 2]]
$ [
1,
2
]
s[[1, x]]
$ +---+-----------+
| x | s[[1, x]] |
+---+-----------+
| 2 | [1,2] |
| 4 | [1,4] |
+---+-----------+

多表达式

规则通常是多表达式的,包含到documents的引用。下面定义了一个数组,每个数组包含一个服务的应用名称和主机名称

apps_and_hostnames[[name, hostname]] {
some i, j, k
name := apps[i].name
server := apps[i].servers[_]
sites[j].servers[k].name == server
hostname := sites[j].servers[k].hostname
}
apps_and_hostnames[x]
$ +----------------------+-----------------------+
| x | apps_and_hostnames[x] |
+----------------------+-----------------------+
| ["mongodb","oxygen"] | ["mongodb","oxygen"] |
| ["mysql","carbon"] | ["mysql","carbon"] |
| ["mysql","lithium"] | ["mysql","lithium"] |
| ["web","beryllium"] | ["web","beryllium"] |
| ["web","boron"] | ["web","boron"] |
| ["web","helium"] | ["web","helium"] |
| ["web","hydrogen"] | ["web","hydrogen"] |
| ["web","nitrogen"] | ["web","nitrogen"] |
+----------------------+-----------------------+

推导式

与规则类似,推导式有一个head和一个body。

region := "west"
names := [name | sites[i].region == region; name := sites[i].name]
$ +-----------------+--------+
| names | region |
+-----------------+--------+
| ["smoke","dev"] | "west" |
+-----------------+--------+

这与python中的推导式类似

# Python equivalent of Rego comprehension shown above.
names = [site.name for site in sites if site.region == "west"]

数组推导式

格式如下:

[ <term> | <body> ]
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]
}
app_to_hostnames[app]
$ +-----------+------------------------------------------------------+
| app | app_to_hostnames[app] |
+-----------+------------------------------------------------------+
| "mongodb" | ["oxygen"] |
| "mysql" | ["lithium","carbon"] |
| "web" | ["hydrogen","helium","beryllium","boron","nitrogen"] |
+-----------+------------------------------------------------------+

对象推导式

格式如下:

{ <key>: <term> | <body> }

注意key不能有冲突

app_to_hostnames := {app.name: hostnames |
app := apps[_]
hostnames := [hostname |
name := app.servers[_]
s := sites[_].servers[_]
s.name == name
hostname := s.hostname]
}
app_to_hostnames[app]
$ +-----------+------------------------------------------------------+
| app | app_to_hostnames[app] |
+-----------+------------------------------------------------------+
| "mongodb" | ["oxygen"] |
| "mysql" | ["lithium","carbon"] |
| "web" | ["hydrogen","helium","beryllium","boron","nitrogen"] |
+-----------+------------------------------------------------------+

集合推导式

格式如下:

{ <term> | <body> }
a := [1, 2, 3, 4, 3, 4, 3, 4, 5]
b := {x | x = a[_]}
$ +---------------------+-------------+
| a | b |
+---------------------+-------------+
| [1,2,3,4,3,4,3,4,5] | [1,2,3,4,5] |
+---------------------+-------------+

规则

集合

返回结果是一个集合

hostnames[name] { name := sites[_].servers[_].hostname }
hostnames[name]
$ +-------------+-----------------+
| name | hostnames[name] |
+-------------+-----------------+
| "beryllium" | "beryllium" |
| "boron" | "boron" |
| "carbon" | "carbon" |
+-------------+-----------------+
对象

返回结果是一个可检索的对象

apps_by_hostname[hostname] = app {
some i
server := sites[_].servers[_]
hostname := server.hostname
apps[i].servers[_] == server.name
app := apps[i].name
}
apps_by_hostname["helium"]
$ "web"
增量定义

增量定义实际就是逻辑或

如下,将serverscontainers 数据抽象为 instances:

instances[instance] {
server := sites[_].servers[_]
instance := {"address": server.hostname, "name": server.name}
} instances[instance] {
container := containers[_]
instance := {"address": container.ipaddress, "name": container.name}
}
完整定义

除了使用部分规则定义集合和对象,还可以使用完整规则,完整规则忽略了head中的key,通常用于表示常量

pi := 3.14159

完整定义一次性赋予一个值,如下将32和4赋值给max_memory就会发生错误

# Power users get 32GB memory.
max_memory = 32 # Restricted users get 4GB memory.
max_memory = 4 $ module.rego:8: eval_conflict_error: complete rules must not produce multiple outputs

使用:=时,每个包中只能声明一个相同名称的完整定义:

package example

pi := 3.14

# some other rules...

pi := 3.14156   # Redeclaration error because 'pi' already declared above.
函数

Rego支持自定义函数,这些函数可以与内置函数一样调用。函数可以有任意多个输入,但只能有一个输出

trim_and_split(s) = x {
t := trim(s, " ")
x := split(t, ".")
}
trim_and_split(" foo.bar ")
$ [
"foo",
"bar"
]

一个函数可以定义多次,用于实现通过条件来选择所要执行的函数:

q(1, x) = y {
y := x
}
q(2, x) = y {
y := x*4
}
q(1, 2)
$ 2
q(2, 2)
$ 8

但在调用时需要注意,入参不能匹配多个函数

r(1, x) = y {
y := x
} r(x, 2) = y {
y := x*4
}
r(1, 2)
$ module.rego:3: eval_conflict_error: functions must not produce multiple outputs for same inputs

注意,如果无法匹配到函数,则结果是未定义的:

s(x, 2) = y {
y := x * 4
}
s(5, 3)
$ undefined decision

否定

t {
greeting := "hello"
not greeting == "goodbye"
}
t
$ true

下面用于分别找出在和不在prod环境的app:

prod_servers[name] {
site := sites[_]
site.name == "prod"
name := site.servers[_].name
} apps_in_prod[name] {
app := apps[_]
server := app.servers[_]
prod_servers[server] #过滤出在prod的app,行与行之间是与的关系,如果不存在则不会执行下一个语句,即name不会被赋值
name := app.name
} apps_not_in_prod[name] {
name := apps[_].name
not apps_in_prod[name]
}

全量(FOR ALL)

Rego没有直接的方式来表示全量("FOR ALL")。例如需要找出名称非"bitcoin-miner"的app时,使用如下方式是错误的,无论apps中是否存在名为"bitcoin-miner"的app,最终都会返回true

no_bitcoin_miners {
app := apps[_]
app.name != "bitcoin-miner" # THIS IS NOT CORRECT.
}

可以使用如下方式来实现上述目的:

no_bitcoin_miners_using_negation {
not any_bitcoin_miners
} any_bitcoin_miners {
some i
app := apps[i]
app.name == "bitcoin-miner"
}

此外还可以使用推导式实现:

no_bitcoin_miners_using_comprehension {
bitcoin_miners := {app | app := apps[_]; app.name == "bitcoin-miner"}
count(bitcoin_miners) == 0
}

模块

在rego中,策略被定义在模块中,一个模块需要包含:

注释

使用#进行注释

package

包可以将一个或多个模块中的规则打包到特定的命名空间中。

import

模块中可以使用datainput引用文本

如在 kubernetes.admission中定义了一个规则 deny:

package kubernetes.admission

deny[msg] {
input.request.kind.kind == "Pod"
some i
image := input.request.object.spec.containers[i].image
not startswith(image, "hooli.com/")
msg := sprintf("image '%v' comes from untrusted registry", [image])
}

在另一个包中可以通过如下方式引用deny规则:

{
"user": "alice",
"action": "read",
"object": "id123",
"type": "dog"
}
package app.rbac
import data.kubernetes.admission deny[input.user]

some关键字

With 关键字

with关键字允许查询以编程方式指定嵌套在input 文档data 文档下的值。with关键字充当表达式的修饰符。一个表达式可以有零或多个with修饰符。

格式如下,必须是对input文档或data文档中的值的引用。当应用于data文档时,不能尝试部分定义虚拟文档(例如一个给定的虚拟文档路径为data.foo.bar,如果策略试图替换data.foo.bar.baz,那么编译器将产生错误)。

<expr> with <target-1> as <value-1> [with <target-2> as <value-2> [...]]

举例如下:

allow with input as {"user": "charlie", "method": "GET"} with data.roles as {"dev": ["charlie"]}

with关键字仅影响连接表达符,后续表达式将看到未修改的值。下面是一种例外(input.foo=1,input.bar=2),outer中的输入在middle中进行了计算

inner := [x, y] {
x := input.foo
y := input.bar
} middle := [a, b] {
a := inner with input.foo as 100
b := input
} outer := result {
result := middle with input as {"foo": 200, "bar": 300} #middle中修改了a
}
{
"inner": [
1,
2
],
"middle": [
[
100,
2
],
{
"bar": 2,
"foo": 1
}
],
"outer": [
[
100,
300
],
{
"bar": 300,
"foo": 200
}
]
}

Default 关键字

default关键字允许策略为具有完整定义的规则生成的文档定义默认值。格式如下:

default <name> = <term>

用法如下,如果没有default,则会返回undefined

default allow = false

allow {
input.user == "bodddb"
input.method == "GEdddT"
} allow {
input.user == "aliddce"
}

Else 关键字

与编程语言中的else类似

authorize = "allow" {
input.user == "superuser" # allow 'superuser' to perform any operation.
} else = "deny" {
input.path[0] == "admin" # disallow 'admin' operations...
input.source_network == "external" # from external networks.
} # ... more rules

操作符

成员和迭代:in

需要import future.keywords。成员操作符in用于检查一个元素是否存在于array, set, 或 object中,返回truefalse

import future.keywords.in

p = [x, y, z] {
x := 3 in [1, 2, 3] # array
y := 3 in {1, 2, 3} # set
z := 3 in {"foo": 1, "bar": 3} # object
}
{
"p": [
true,
true,
true
]
}

当在in操作符左侧提供两个参数,且右侧为object或array,则第一个参数作为key(object)或index(array):

import future.keywords.in

p := [ x, y ] {
x := "foo", "bar" in {"foo": "bar"} # key, val with object
y := 2, "baz" in ["foo", "bar", "baz"] # key, val with array
}
{
"p": [
true,
true
]
}

注意在列表(如集合或数组以及函数参数)上下文中需要使用圆括号来让两侧参数一一对应

import future.keywords.in

p := x {
x := { 0, 2 in [2] } #这是一个集合,表示0和2 in [2]
}
q := x {
x := { (0, 2 in [2]) }#这是一个集合,但计算的是0, 2 in [2]
}
w := x {
x := g((0, 2 in [2]))#g(x)只有一个参数,需要使用圆括号括起来
}
z := x {
x := f(0, 2 in [2])#f(x)有两个参数,第一个参数是0,第二个参数是2 in [2]
} f(x, y) = sprintf("two function arguments: %v, %v", [x, y])
g(x) = sprintf("one function argument: %v", [x])

not结合使用,可以很方便地断言一个元素是否是数组的成员:

import future.keywords.in

deny {
not "admin" in input.user.roles
} test_deny {
deny with input.user.roles as ["operator", "user"]
}
{
"test_deny": true
}

使用some,可以根据不同的类型引入新的变量

import future.keywords.in

p[x] {
some x in ["a", "r", "r", "a", "y"]
} q[x] {
some x in {"s", "e", "t"}
} r[x] {
some x in {"foo": "bar", "baz": "quz"}
}
{
"p": [
"a",
"r",
"y"
],
"q": [
"e",
"s",
"t"
],
"r": [
"bar",
"quz"
]
}

使用两个参数可以检索object的关键字和array的索引

import future.keywords.in

p[x] {
some x, "r" in ["a", "r", "r", "a", "y"] # key variable, value constant
} q[x] = y {
some x, y in ["a", "r", "r", "a", "y"] # both variables
} r[y] = x {
some x, y in {"foo": "bar", "baz": "quz"}
}
{
"p": [
1,
2
],
"q": {
"0": "a",
"1": "r",
"2": "r",
"3": "a",
"4": "y"
},
"r": {
"bar": "foo",
"quz": "baz"
}
}

some变量的任何参数都可以是复合的非基础值:

import future.keywords.in

p[x] = y {
some x, {"foo": y} in [{"foo": 100}, {"bar": 200}]#x为key为foo的数组索引,y为key为foo的值
}
p[x] = y {
some {"bar": x}, {"foo": y} in {{"bar": "b"}: {"foo": "f"}} # x为bar的值,y为foo的值
}
{
"p": {
"0": 100,
"b": "f"
}
}

等式:赋值,比较和联合

Rego支持三种等式:赋值(:=),比较()和联合(=)。建议使用赋值(:=)和比较()。

赋值 :=

可以使用一种简单的解构形式将数组中的值解包并将其分配给变量

address := ["3 Abbey Road", "NW8 9AY", "London", "England"]

in_london {
[_, _, city, country] := address
city == "London"
country == "England"
}
{
"address": [
"3 Abbey Road",
"NW8 9AY",
"London",
"England"
],
"in_london": true
}
比较 ==
联合 =

Rego会将比较为真的值赋于变量。联合可以赋予变量使表达式为true的值。

sites[i].servers[j].name = apps[k].servers[m]
+---+---+---+---+
| i | j | k | m |
+---+---+---+---+
| 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 1 |
| 0 | 2 | 1 | 0 |
| 1 | 0 | 0 | 2 |
| 1 | 1 | 0 | 3 |
| 1 | 2 | 1 | 1 |
| 2 | 0 | 0 | 4 |
| 2 | 1 | 2 | 0 |
+---+---+---+---+

比较表达式

a  ==  b  #  `a` is equal to `b`.
a != b # `a` is not equal to `b`.
a < b # `a` is less than `b`.
a <= b # `a` is less than or equal to `b`.
a > b # `a` is greater than `b`.
a >= b # `a` is greater than or equal to `b`.

内置函数

内置函数的格式如下:

<name>(<arg-1>, <arg-2>, ..., <arg-n>)

错误

默认情况下,遇到运行时错误的内置函数调用会将结果设为undefined (通常可以被视为false),且不会停止策略计算。这种方式可以保证在使用调用内置函数时,输入无效参数不会导致整个策略停止计算。

策略相关

Assignment and Equality

# assign variable x to value of field foo.bar.baz in input
x := input.foo.bar.baz # check if variable x has same value as variable y
x == y # check if variable x is a set containing "foo" and "bar"
x == {"foo", "bar"} # OR {"foo", "bar"} == x

Lookup

Arrays
# lookup value at index 0
val := arr[0] # check if value at index 0 is "foo"
"foo" == arr[0] # find all indices i that have value "foo"
"foo" == arr[i] # lookup last value
val := arr[count(arr)-1] # with `import future.keywords.in`
some 0, val in arr # lookup value at index 0
0, "foo" in arr # check if value at index 0 is "foo"
some i, "foo" in arr # find all indices i that have value "foo"
Objects
# lookup value for key "foo"
val := obj["foo"] # check if value for key "foo" is "bar"
"bar" == obj["foo"] # OR "bar" == obj.foo # check if key "foo" exists and is not false
obj.foo # check if key assigned to variable k exists
k := "foo"
obj[k] # check if path foo.bar.baz exists and is not false
obj.foo.bar.baz # check if path foo.bar.baz, foo.bar, or foo does not exist or is false
not obj.foo.bar.baz # with `import future.keywords.in`
o := {"foo": false}
# check if value exists: the expression will be true
false in o
# check if value for key "foo" is false
"foo", false in o
Sets
# check if "foo" belongs to the set
a_set["foo"] # check if "foo" DOES NOT belong to the set
not a_set["foo"] # check if the array ["a", "b", "c"] belongs to the set
a_set[["a", "b", "c"]] # find all arrays of the form [x, "b", z] in the set
a_set[[x, "b", z]] # with `import future.keywords.in`
"foo" in a_set
not "foo" in a_set
some ["a", "b", "c"] in a_set
some [x, "b", z] in a_set

Iteration

Arrays
# iterate over indices i
arr[i] # iterate over values
val := arr[_] # iterate over index/value pairs
val := arr[i] # with `import future.keywords.in`
some val in arr # iterate over values
some i, _ in arr # iterate over indices
some i, val in arr # iterate over index/value pairs
Objects
# iterate over keys
obj[key] # iterate over values
val := obj[_] # iterate over key/value pairs
val := obj[key] # with `import future.keywords.in`
some val in obj # iterate over values
some key, _ in obj # iterate over keys
some key, val in obj # key/value pairs
Sets
# iterate over values
set[val] # with `import future.keywords.in`
some val in set
Advanced
# nested: find key k whose bar.baz array index i is 7
foo[k].bar.baz[i] == 7 # simultaneous: find keys in objects foo and bar with same value
foo[k1] == bar[k2] # simultaneous self: find 2 keys in object foo with same value
foo[k1] == foo[k2]; k1 != k2 # multiple conditions: k has same value in both conditions
foo[k].bar.baz[i] == 7; foo[k].qux > 3

For All

# assert no values in set match predicate
count({x | set[x]; f(x)}) == 0 # assert all values in set make function f true
count({x | set[x]; f(x)}) == count(set) # assert no values in set make function f true (using negation and helper rule)
not any_match # assert all values in set make function f true (using negation and helper rule)
not any_not_match
any_match {
set[x]
f(x)
} any_not_match {
set[x]
not f(x)
}

Rules

In the examples below ... represents one or more conditions.

Constants
a = {1, 2, 3}
b = {4, 5, 6}
c = a | b
Conditionals (Boolean)
# p is true if ...
p = true { ... } # OR p { ... }
Conditionals
default a = 1
a = 5 { ... }
a = 100 { ... }
Incremental
# a_set will contain values of x and values of y
a_set[x] { ... }
a_set[y] { ... } # a_map will contain key->value pairs x->y and w->z
a_map[x] = y { ... }
a_map[w] = z { ... }
Ordered (Else)
default a = 1
a = 5 { ... }
else = 10 { ... }
Functions (Boolean)
f(x, y) {
...
} # OR f(x, y) = true {
...
}
Functions (Conditionals)
f(x) = "A" { x >= 90 }
f(x) = "B" { x >= 80; x < 90 }
f(x) = "C" { x >= 70; x < 80 }

open policy agent 语法总结的更多相关文章

  1. Dapr 集成 Open Policy Agent

    大型项目中基本都包含有复杂的访问控制策略,特别是在一些多租户场景中,例如Kubernetes中就支持RBAC,ABAC等多种授权类型.Dapr 的 中间件 Open Policy Agent 将Reg ...

  2. Policy Gradient Algorithms

    Policy Gradient Algorithms 2019-10-02 17:37:47 This blog is from: https://lilianweng.github.io/lil-l ...

  3. 用sc命令查询系统状态

    用sc命令查询系统状态 sc query 语法 sc query                - Enumerates status for active services & driver ...

  4. vpn找不到设备,win7建立新的VPN总时显示错误711,无法启动 Remote Access Connection Manager 及 Remote Access Auto Connection Manager 错误1068

    试试相关服务!一.remote access connection manager是网络连接的服务,它依赖于Technology服务,现在你的这个服务已经启动,而Secure Socket Tunne ...

  5. [讨论] win7封装时如何直接开通局域网共享

    ekincheng 发表于 2016-10-31 20:17:54 https://www.itsk.com/thread-371838-1-5.html Win7封装时不能像XP那样直接开启局域网共 ...

  6. 终极优化_详解Win7旗舰版系统中可以关闭的服务

    Win7旗舰版系统是一款功能强大的系统,不过对于很多用户很多功能却使用不上,而支持功能的很多服务也多少占用了系统资源,那么我们可以通过关闭一些不使用的服务来达到让win7系统运行速度加快的目的.下面小 ...

  7. Secure Socket Tunneling Protocol Service服务无法启动(win7)

    第一种方法: 1.确认一下服务都开启: Base Filtering Engine IKE and Authip IPsec Keying Module Ipsec Policy Agent Wind ...

  8. win2003 服务器安全设置详细介绍

    第一步:一.先关闭不需要的端口  我比较小心,先关了端口.只开了3389 21 80 1433(MYSQL)有些人一直说什么默认的3389不安全,对此我不否认,但是利用的途径也只能一个一个的穷举爆破, ...

  9. Win7 服务优化个人单机版

    我的PC设备比较旧了,为了系统能流畅点,不必要的服务就不开启了.然而,服务那么多,每次重装,都要从头了解一下一边,浪费时间. 个人在网络上收集信息并结合自己的摸索,整理如下,以备查找. 服务名称  显 ...

随机推荐

  1. Redis 的 3 种集群方案对比

    数据持久化 主从复制 自动故障恢复 集群化 数据持久化本质上是为了做数据备份,有了数据持久化,当Redis宕机时,我们可以把数据从磁盘上恢复回来,但在数据恢复之前,服务是不可用的,而且数据恢复的时间取 ...

  2. Orthogonal Convolutional Neural Networks

    目录 概 主要内容 符号说明 的俩种表示 kernel orthogonal regularization orthogonal convolution Wang J, Chen Y, Chakrab ...

  3. 利用 jQuery 操作页面元素的方法,实现电商网站购物车页面商品数量的增加和减少操作,要求单项价格和总价随着数量的改变而改变

    查看本章节 查看作业目录 需求说明: 利用 jQuery 操作页面元素的方法,实现电商网站购物车页面商品数量的增加和减少操作,要求单项价格和总价随着数量的改变而改变 当用户单击"+" ...

  4. Docker | dockerfile 文件编写

    dockerfile 的作用 dockerfile 作用就是制作镜像,保持开发,测试,生产环境的一致性. 直接将容器制作为镜像 制作新的镜像 # 把容器按照自己的需求个性完之后,就可以创建自己的镜像的 ...

  5. openmesh - impl - Remove Duplicated Vertices

    openmesh - impl - Remove Duplicated Vertices 关于openmesh元素删除实现的介绍参见:openmesh - src - trimesh delete a ...

  6. Fuchsia OS入门官方文档

    Fuchsia Pink + Purple == Fuchsia (a new Operating System) Welcome to Fuchsia! This document has ever ...

  7. LINUX学习-PHP安装

    一.安装环境 操作系统CentOS6.8 关闭SeLinux和iptables防火墙 二.网络yum源 将下面的软件下载到  /etc/yum.repos.d/   的目录下 官方基础:http:// ...

  8. WAFW00F waf识别工具 源码学习

    我实习工作的第一个任务根据已有的java waf识别工具 实现了一个python的waf识别工具 代码结构非常乱 仅仅达到了能用的水平. 顶头svp推荐这个项目当时我已经写好了开始用了自己的 稍微看了 ...

  9. EF4中多表关联查询Include的写法

    大家好,好久没有写作了,最近遇到了个问题,最终是靠自己的尝试写出来的,希望可以帮到有需要的人. 在我们查询时通常会遇到多级表关联的情况,很多时候有人会想写一个from LINQ语句来解决,那么冗长的代 ...

  10. Solon 开发,七、自定义注解开发汇总

    Solon 开发 一.注入或手动获取配置 二.注入或手动获取Bean 三.构建一个Bean的三种方式 四.Bean 扫描的三种方式 五.切面与环绕拦截 六.提取Bean的函数进行定制开发 七.自定义注 ...