简介
官网介绍
OPA简单的说就是一个功能强大的策略规则引擎,开发的时候多少会遇到一些多样的规则配置,这些配置不足以写到数据库,所以都写到了代码中、配置文件中。项目做大的时候,如果需要修改规则,那么只能重新修改代码,打包发布,相对比较麻烦,还增加了业务的复杂度,这个时候OPA的作用就出来了,它可以把这些配置的的东西独立出来,让规则脱离主业务逻辑。
安装
OPA是一个很简单的东西,直接下载放到Linux的sbin下就能直接使用了
macOS (64-bit): https://openpolicyagent.org/downloads/latest/opa_darwin_amd64
Linux下载:https://openpolicyagent.org/downloads/latest/opa_linux_amd64
以Linux为例,把名称修改下 opa_linux_amd64 改为 opa,然后设置文件可执行,再然后丢到/usr/bin目录下就能用了。
# Ubuntu 默认下载到 Downloads 目录下面
# 剪切刚才下载的opa可执行文件到 /usr/bin/目录下,并且重命名为 opa
sudo mv opa_linux_amd64 /usr/bin/opa
# 赋予它可执行权限
sudo chmod +x opa
# 测试
opa 回车
tommy@tommy-Vostro-3900:~/Downloads$ opa
An open source project to policy-enable your service.
Usage:
opa [command]
Available Commands:
bench Benchmark a Rego query
build Build an OPA bundle
check Check Rego source files
deps Analyze Rego query dependencies
eval Evaluate a Rego query
fmt Format Rego source files
help Help about any command
parse Parse Rego source file
run Start OPA in interactive or server mode
sign Generate an OPA bundle signature
test Execute Rego test cases
version Print the version of OPA
Flags:
-h, --help help for opa
Use "opa [command] --help" for more information about a command.
实测
OPA官方给出了一个在线测试的地址
测试地址
实战
语法规则
基本语法
OPA基于一种数据查询语言实现了描述语言Rego
OPA的Rego基本语法如下表:
语法 | 例子 | 上下文 | data | 输入 | input | 索引取值 | data.bindings[0] | 比较 | “alice” == input.subject.user | 赋值 | user := input.subject.user | 规则 | < Header > { < Body > } | 规则头 | < Name > = < Value > { … } 或者 < Name > { … } | 规则体 | And运算的一个个描述 | 多条同名规则 | Or运算的一个规则 | 规则默认值 | default allow = false | 函数 | fun(x) { … } | 虚拟文档 | doc[x] { … } |
rule
当定义规则时:
-
- 格式2
< Name > = < Value > { ... }
- 声明返回值
< Value > 则返回其值 - 规则体内每条描述会逐条
And 运算,全部成立才会返回值 - 多条同名规则相互之间是
Or 运算,满足其一即可
具体到代码中规则allow , 默认值是false
要求user_has_role 和role_has_permission 同时满足
两者的role_name 也是一样。
你可能发现,局部变量role_name 没声明啊!
Rego 里可以省略声明局部变量, 直接使用。
事例
规则描述
高考中规定的分数线,不同城市的本科分数线是不一样的,小明考试查询下分数,需要往系统录入考试城市,以及考试分数,用来查询,即:
{
"alias": "shenzhen",
"score": 600
}
规则数据Data
{
"achievement": {
"shenzhen": {
"yiben": {
"score": 600
},
"erben": {
"score": 500
}
},
"guangzhou":{
"yiben": {
"score": 620
},
"erben": {
"score": 520
}
}
}
规则逻辑代码
package app.rbac
# 查询分数线是否满足条件
result = {"score_line": 1, "msg": "恭喜你考上一本"} {
data.achievement[input.alias].yiben.score <= input.score
} else = {"score_line": 2, "msg": "恭喜你考上二本"}{
data.achievement[input.alias].erben.score <= input.score
} else = {"score_line": -1, "msg": "没考上"}
运行测试结果
本地opa跑代码
创建一个文件夹 tommy 然后在tommy文件夹下再创建 tommytest 把三个文件丢到tommytest目录下
文件名称随意,标准的是:input.json data.json policy.rego
文件内容分别为:
input.json文件
{
"alias": "shenzhen",
"score": 600
}
data.json文件
{
"achievement": {
"shenzhen": {
"yiben": {
"score": 600
},
"erben": {
"score": 500
}
},
"guangzhou": {
"yiben": {
"score": 620
},
"erben": {
"score": 520
}
}
}
}
package tommytest
# 查询分数线是否满足条件
result = {"score_line": 1, "msg": "恭喜你考上一本"} {
data.tommytest.achievement[input.alias].yiben.score <= input.score
} else = {"score_line": 2, "msg": "恭喜你考上二本"}{
data.tommytest.achievement[input.alias].erben.score <= input.score
} else = {"score_line": -1, "msg": "没考上"}
然后,回到tommy文件夹目录,执行命令
opa eval --bundle . -i tommytest/input.json 'data.tommytest.result'
# 返回的结果
{
"result": [
{
"expressions": [
{
"value": {
"msg": "恭喜你考上一本",
"score_line": 1
},
"text": "data.tommytest.result",
"location": {
"row": 1,
"col": 1
}
}
]
}
]
}
|