opa 策略引擎教程
前言
Open Policy Agent (OPA)是一个使用 golang 语言实现的开源通用策略引擎。OPA 主要由以下 3 个核心部分:
- Rego:OPA 语言的名称,用来编写策略规则。
- Input:需要执行策略计算的原始数据
- Output:Rego 的计算结果
Rego 的灵感来自 Datalog。而 Datalog 是一种声明式逻辑编程语言,它在语法上是 Prolog 的子集。
在线体验
官方提供了一个 Playgroud,支持在线执行,整个界面窗口分为如下四块:
- 左侧一整块是 Policy 窗口:在此处使用 Rego 进行编写策略。
- 右上方是 Input 窗口:规则需要的外部数据在此处定义,比如 JSON 或 YAML 格式的数据。
- 右中间是 Data 窗口:若规则计算除了需要外部数据,还需要内部数据做比对,则可以在此定义。
- 右下方是 Output 窗口:OPA 进行策略决策后的结果输出区域,在 playground 这种方式中会将全部信息都输出给我们,没有办法指定查询指定的字段值,官方提示的示例中输出为布尔值。
可以点击 Examples 切换不同的例子,然后点击 Evaluate 执行查看结果。
可以使用 Rego 语法编写自己的策略,如:
package cn.sxy21.demo1
import future.keywords.if
import future.keywords.in
import future.keywords.contains
default good := false
good if {
# 如果 user 存在 pet 字段
input.user.pet
# 如果 user 的 pet 中含有 cat
"cat" in input.user.pet
# 如果 user 的 gender 是 M
input.user.gender == "M"
# 下方的等价为:是否存在 address 且 adress 不是 beijing
# input.user.address != "beijing"
}
# have contains money :当里面的条件满足时 在 have 这个集合里放入 money 的值
have contains money {
input.user.height >= 175
money:= "Dollar"
}
have contains money {
input.user.age < 20
money:= "RMB"
}
然后使用 input
{
"user": {
"name": "song yang cong",
"site": [
"sxy21.cn",
"sxy91.com"
],
"age": 18,
"height": 180,
"email": "sxy996@qq.com",
"gender": "M",
"pet": [
"cat",
"dog",
"elephant",
"peacock"
]
}
}
执行结果:
{
"good": true,
"have": [
"Dollar",
"RMB"
]
}
或(or)操作
上面的例子都是 and 操作,如何表示 or 操作 呢?
规则:当服务器的协议包含 telnet 或者 ssh 时,输出服务器的 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"
}
输入:
{
"servers": [
{
"id": "busybox",
"protocols": ["http", "telnet"]
},
{
"id": "db",
"protocols": ["mysql", "ssh"]
},
{
"id": "web",
"protocols": ["https"]
}
]
}
输出:
[
"busybox",
"db"
]
安装 OPA
使用官方镜像仓库 openpolicyagent/opa
# pull
docker pull openpolicyagent/opa
# run on console
docker run -it --rm openpolicyagent/opa
# test
> pi := 3.14
> pi
# 3.14
> pi > 3
# true
exit
# 后台运行
docker run -itd -p 8181:8181 openpolicyagent/opa run --server --addr :8181
基于 rest api 使用
OPA REST API:
- 先创建策略
PUT /v1/policies/<id>
curl --request PUT \
--url http://localhost:8181/v1/policies/p001 \
--header 'content-type: text/plain' \
--data 'package cn.sxy21.demo1
import future.keywords.in
default resutl := false
resutl {
"cat" in input.user.pet
input.user.gender == "M"
}'
package
具有唯一性,多个 policy 不允许出现相同的包名。
- 使用 input 数据验证策略
路径为:/v1/data/{包名(把“.”替换成"/")}/{default 描述的部分}
使用步骤 1 中的
package
来定位使用哪个 policy
curl --request POST \
--url http://localhost:8181/v1/data/cn/sxy21/demo1/resutl \
--header 'content-type: application/json' \
--data '{
"input":{
"user": {
"name": "song yang cong",
"site": [
"sxy21.cn",
"sxy91.com"
],
"age": 18,
"height": 180,
"email": "sxy996@qq.com",
"gender": "F",
"pet": [
"cat",
"dog",
"elephant",
"peacock"
]
}
}
}'
结果:
{
"result": false
}