作者 | 刘林
前言
在实际生产环境中,许多场景需要进行策略控制,例如,不同团队的API需要限制访问权限,以避免未经授权的网络访问。为实现这种控制,可以采用策略控制的方法。然而,实施策略控制需要修改代码,而且策略通常很分散。为了解决这个问题,可以使用OPA(Open Policy Agent)进行策略控制。
OPA 可以通过定义的策略查询输入数据,并生成决策。例如:
- 控制哪些用户可以访问哪些资源
- 控制用户是否有权访问服务器或执行某些操作
- 控制哪些项目/组件可以部署
- 控制如何访问数据库
- 控制哪些资源可以部署到 Kubernetes 中
OPA简介及原理
OPA 是什么
OPA(Open Policy Agent)是一个开源的通用策略引擎,由 Styra 公司于2016年创建并开源,目前已是 CNCF 的毕业项目。其主要功能是将策略决策与应用程序的业务逻辑分离,将策略看作一组规则。请求被发送到引擎后,引擎会根据规则来进行决策。OPA 并不负责具体任务的执行,它仅负责决策。请求通过 JSON 方式传递给 OPA,决策结果也以 JSON 的形式返回。OPA将策略配置统一到一处,极大地降低维护成本,并将策略与对应的软件/服务解耦,方便进行移植和复用。
OPA 策略
OPA 中的策略是以 Rego 这种DSL(Domain Specific Language)来表示的。每个规则都是由头部和主体组成。在 Rego 中,如果规则主体对于某些变量赋值为真,那么我们说规则头为真。可以通过绝对路径引用任何加载到 OPA 中的规则来查询它的值。规则的路径总是:data.PACKAGE.RULE (规则生成的所有值都可以通过全局 data 变量进行查询) 。如果有多个规则相同,则一旦匹配到一个为true的规则,就为true。下面的案例中有具体代码,可在后面的章节详细了解rego编写。
OPA 原理
OPA 将策略执行与决策解耦。当软件需要做出决策时,它向OPA 查询并提供结构化数据(例如JSON)作为输入。其工作原理如下图所示:
- 请求达到OPA Server之后,OPA会将输入的JSON数据作为数据源,并使用定义的规则进行查询。
- OPA 将查询的结果返回给Server端。
- Service端根据查询的结果放行或拒绝request。
如何使用OPA
案例一:OPA 实现API权限控制
如果要实现放行角色为admin的用户请求,并且所有人都能够访问路径为/public的GET类型的API,我们可以探究一下OPA 如何实现这个需求:
规则代码
文件名: policy.rego
文件名: input.json
测试代码
文件名: policy_test.rego
使用命令行验证policy逻辑
如下命令使用input.json文件来验证是否能满足policy.rego文件中的data.policy.allow规则。
附:如只想查看最终结果,可加上--format raw参数,输出如下
使用OPA server验证policy逻辑
opa run 会启动一个交互式 shell ( REPL) 。我们可以使用 REPL 来试验策略和构建策略。
“读取-求值-输出” 循环(Read-Eval-Print Loop,简称REPL)
我们也可以将策略直接加载进去,或者将 OPA 作为一个服务运行并通过 HTTP 执行查询。默认情况下,OPA 监会监听在 8181 端口。
打开postman访问 OPA server, postman信息如下
OPA策略执行流程分析
下图中的请求何满足策略规则呢?
上图请求表示,使用OPA Server中policy包中的allow规则校验该请求。
(1) 查看第一条allow策略
该策略中仅允许roles是admin的用户执行操作,查看我们postman中body数据,得知roles是developer,顾这条策略不满足,OPA会继续查看其他策略。
(2) 查看第二条allow策略
该策略中仅允许request path是/public开头且请求方法是GET的请求, 满足我们postman中的request内容,顾该请求满足策略要求。
案例二:OPA在Kubernetes中的使用案例
由于OPA应用到Kubernetes中时,需要较多的Kubernetes基础,这里想淡化对Kubernetes基础的要求,所以使用Gatekeeper来集成Kubernetes。
Gatekeeper是一个开源的使用OPA来定义和执行策略的系统
下文将实现不允许在default namespace中部署deployment资源的案例。
部署Gatekeeper到Kubernetes
Kubernetes中的策略
(1) 策略文件准备
文件名:template.yaml
图片
文件名:constraint.yaml
图片
文件名nginx-app.yaml
(2) 创建策略
验证策略
(1) 尝试在default namespace中创建deployment资源
尝试创建资源的时候,会出现如下报错,因为OPA策略中已经指定,不允许在default namespace中创建deployment资源。
(2) 尝试在其他namespace中创建deployment资源
创建demo namespace,并尝试在该namespace中创建deployment资源,可成功创建。
图片
总结
- OPA是一个开放源代码的通用策略引擎,将策略决策与应用程序的业务逻辑分离。
- OPA将输入的JSON数据作为数据源,使用定义的规则进行查询,返回最终的结果(allow 或者 deny)。
- 目前基于OPA的产品有Gatekeeper, Styra。如果是项目使用的话,个人推荐使用Styra,因为Styra的策略和input数据是有可视化页面的,使用和排错成本较低。
- Rego是基于查询进行断言的语言,基于规则查询结果,给出true或false的查询语言。