OPA-重新定义规则引擎-入门篇 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
newmiao
V2EX    Go 编程语言

OPA-重新定义规则引擎-入门篇

  •  1
     
  •   newmiao 2020-03-15 20:52:55 +08:00 3696 次点击
    这是一个创建于 2037 天前的主题,其中的信息可能已经有所发展或是发生改变。

    OPA,全称OpenPolicyAgent, 底层用Go实现,它灵活而强大的声明式语言全面支持通用策略定义。

    目前国内资料还比较少。

    个人因为工作接触比较多,打算陆续分享些教程介绍下。

    私以为规则引擎的技术选型完全可以多这个选择~~

    什么是 OPA

    具体看官方文档 OPA philosophy docs

    主要关键词是:

    • 轻量级的通用策略引擎
    • 可与服务共存
    • 集成方式可以是 sidecar、主机级守护进程或库引入

    opa

    文字图片还是不够生动,看看 OPA 作者怎么说:

    OPA: The Cloud Native Policy Engine - Torin Sandall, Styra

    备用国内 B 站地址

    优点

    • 强大的声明式策略

      • 上下文感知
      • 表达性强
      • 快速
      • 可移植
    • 输入和输出支持任意格式

    配合强大的声明式策略语言Rego,描述任意规则都不是问题

    • 全面支持规则和系统解耦

    如图

    除了集成做Auth外,还可以应用到k8s,terraform,docker,kafka,sql,linux等上做规则决策

    • 工具齐全
      • 有命令行,有交互式运行环境
      • 支持测试,性能分析(底层Go实现)
      • 有强大的交互式编辑器扩展vscode-opa
      • playground分享代码

    下面从一个 RBAC 鉴权例子来了解下OPA

    一个 RBAC 例子

    以下 json 配置了 role 能操作的资源和 user 的绑定关系

    // data.json { "roles": [ { "operation": "read", "resource": "widgets", "name": "widget-reader" }, { "operation": "write", "resource": "widgets", "name": "widget-writer" } ], "bindings": [ { "user": "inspector-alice", "role": "widget-reader" }, { "user": "maker-bob", "role": "widget-writer" } ] } 

    当一个请求读取 widgets 的 user (如下 json )过来操作资源,怎么判定他是否可以呢?

    // input.json { "action":{ "operation":"read", "resource":"widgets" }, "subject":{ "user":"inspector-alice" } } 

    可能你习惯性在想用自己趁手的语言和框架,一顿遍历循环搞定。

    且慢,OPA告诉我们:

    几行代码就可以!(当然代码少不是重点。。。)

    这里是可以在线运行的代码示例

    example_rbac

    我们先抛开语法,代码其实就是描述了一条规则:

    用户是否有角色,角色是否有权限操作的资源

    下面我们开始学习OPA如何定义这条规则

    基本语法

    OPA基于一种数据查询语言Datalog实现了描述语言Rego

    OPARego基本语法如下表:

    | 语法 | 例子 | | ---- | ---- | | 上下文| 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] { ... }|

    一点也不多。函数和虚拟文档我们后边再开文章展开,今天主要看明白他的规则定义。

    首先输入会挂在input对象下,用到的上下文(就是规则决策基于的源数据)会挂在data对象下

    rule

    当定义规则时:

    • 每条规则都会有返回值

      • 格式 1:< Name > { ... }

      不声明返回值,则只返回 true 或 false

      • 格式 2 < Name > = < Value > { ... }

      声明返回值 < Value > 则返回其值

    • 规则体内每条描述会逐条And运算,全部成立才会返回值

    • 多条同名规则相互之间是Or运算,满足其一即可

    具体到代码中规则allow, 默认值是 false

    要求user_has_rolerole_has_permission同时满足

    两者的role_name也是一样。

    你可能发现,局部变量role_name 没声明啊!

    Rego里可以省略声明局部变量, 直接使用。

    Tips: 但要这样的变量可以被同名的全局变量修改。 局部变量必要时还是应该使用some声明 如 some role_name

    default allow = false # allow will be true when user has role and role has permission allow { user_has_role[role_name] role_has_permission[role_name] } 

    然后其中user_has_role[role_name]这种带参数的结构不是规则,叫虚拟文档(文档:可被查询的集合)

    # check user role binding exist user_has_role[role_name] { role_binding = data.bindings[_] role_binding.role = role_name role_binding.user = input.subject.user } 

    Tips: 仔细同学会发现,线上运行版有withrole_binding = data.bindings[_] with data.bindings as data_context.bindings with 是用来替换输入 input 或者上下文 data 里的数据。 因为线上版没法指定上边的 data.json, 所以通过变量data_context替换传入的。

    集合里边role_binding = data.bindings[_]是遍历data.bindings

    Rego的遍历语法类似 python,这里遍历流程是

    data.bindings一个值赋值给role_binding

    进行后续处理,处理完后再赋下一个值

    Tips: _是特殊变量名,当需要变量占位又不需要后边引用时使用(类似 Go 的_

    至于role_binding.role = role_name这条你应该能猜到是判断请求过来的 role 名是否和配置一致

    可是为什么是=操作符,不应该是==?

    这里是一个有趣的点!

    unification

    Rego中实际只有=,而且作用是为变量赋值使等式成立,叫Unification

    :=局部变量赋值,==比较,是=的语法糖,为了实现局部变量赋值和比较,和编译错误更容易区分

    所以=更像是数据查询。(毕竟Rego是一个数据查询语言嘛)

    这里举个例子就好理解了:

    [x, "world"] = ["hello", y] # 之后,x 值为 hello,y 为 world 

    总结一下,本文介绍什么是OPA,并借一个简单的 RBAC 例子初探了Rego强大的声明规则语法。

    下一篇,将会介绍如何本地优雅的开发OPA,感兴趣同学可以先在OPA的 playground 玩玩。

    了解更多:OPA 的 Rego 文档 本文代码详见:NewbMiao/opa-koans


    文章首发公众号:newbmiao

    推荐阅读:OPA 系列

    4 条回复    2025-05-22 13:25:29 +08:00
    simon8410
        1
    simon8410  
       2020-03-18 15:35:32 +08:00
    写得不错,赞一个
    newmiao
        2
    newmiao  
    OP
       2020-03-20 21:39:38 +08:00
    @simon8410 那是 OPA 真香,用起来很方便
    newmiao
        3
    newmiao  
    OP
       2020-03-21 11:03:03 +08:00
    54qyc
        4
    54qyc  
       143 天前 via Android
    重要的不说,和其他规则引擎的对比呢
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2855 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 23ms UTC 13:53 PVG 21:53 LAX 06:53 JFK 09:53
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86