Authing 文档文档
快速开始
概念
使用指南
开发集成 arrow
  • V2 文档
  • V3 文档
元数据
应用集成
身份自动化
加入 APN
开发集成
多租户(内测版)
控制台文档
多租户控制台
租户控制台
Saas 应用 Demo
快速开始
概念
使用指南
开发集成 arrow
  • V2 文档
  • V3 文档
元数据
应用集成
身份自动化
加入 APN
开发集成
多租户(内测版)
控制台文档
多租户控制台
租户控制台
Saas 应用 Demo
旧版
使用指南
  • 快速开始

  • 对用户进行认证

  • 对用户进行权限管理

    • 选择合适的权限模型
    • 集成 RBAC 权限模型到你的应用系统
    • 集成 ABAC 权限模型到你的应用系统
    • 使用权限分组管理权限资源
    • 管理资源权限
    • 管理新版数据资源权限

      • 权限空间
      • 角色管理
      • 数据资源
      • 数据策略与授权

        • 数据策略与 OPA
      • 权限视图
  • 用户自助服务

  • 授权

  • 自适应 MFA

  • 管理用户账号

  • 管理用户目录

  • 同步中心

  • 应用

  • 成为联邦认证身份源

  • 连接外部身份源(IdP)

  • 微信生态全场景能力

  • 迁移用户到 Authing

  • 管理组织机构

  • 安全设置

  • 品牌化

  • 自动化

  • 审计日志

  • 设置

  • Authing 令牌
  • 私有化部署方案

  • 常见问题 FAQ

  1. 使用指南
  2. /
  3. 对用户进行权限管理
  4. /
  5. 管理新版数据资源权限
  6. /
  7. 数据策略与授权
  8. /
  9. 数据策略与 OPA

¶ 数据策略与 OPA

Policy:根据形势而确定的原则和方法。比如说:当我们生病了,就要去医院看医生,这就是一条策略,编程语言中的if、switch关键字就是很好的体现。

Open Policy Agent 简称OPA是一个使用Go语言编写的开源通用策略引擎。我们编写的代码中可能存在大量的策略,它和服务高度耦合,一旦有所改动,需要重新编译或重新部署。OPA 就能帮我们解决这一痛点,它将策略和服务进行解耦(即策略脱钩,Policy Decoupling),这些策略独立于应用程序而存在。

官网地址:https://www.openpolicyagent.org/ (opens new window)

¶ OPA 的使用

OPA 提供了丰富的RESTful API,我们需要做出策略决策时候,会查询 OPA 并提供结构化数据(JSON)作为输入。注意:OPA 接受任意结构化数据作为输入

OPA1

在 OPA 中对于它的输入一般称为input,可以为任意类型,输出也一样可以为任意类型,即可以输出布尔值 true 或 false,也可以输出一个JSON字符串对象。

我们的权限管理实现了基于属性的访问控制(Attribute-based access control - ABAC),它背后的实现原理是将数据策略中定义的一组组条件转换成 OPA 的策略,并在需要的时候让其帮我们做策略决策(OPA 还有很多用法)

¶ 如何定义 OPA 策略

OPA 中策略使用Rego语言编写的,Rego 的灵感来自 Datalog (opens new window),它是一种易于理解、已有数十年的历史的查询语言。Rego 扩展了 Datalog 以支持 JSON/YAML 等文档模型,对于它的详细介绍请参考官方文档https://www.openpolicyagent.org/docs/latest/policy-language/#what-is-rego (opens new window)

OPA 中的策略在模块(Module)中定义,Module 包含:Package、Import、Rule,除了 Package 是唯一且必须的,另外两个可以 0 或多个。其中 Rule 又是由 Head(定义变量)、Body(定义表达式) 组成。整个 Module 的**抽象语法树(AST)**如下:

Module
 |
 +--- Package (Reference)
 |
 +--- Imports
 |     |
 |     +--- Import (Term)
 |
 +--- Rules
       |
       +--- Rule
             |
             +--- Head
             |     |
             |     +--- Name (Variable)
             |     |
             |     +--- Key (Term)
             |     |
             |     +--- Value (Term)
             |
             +--- Body
                   |
                   +--- Expression (Term | Terms | Variable Declaration)

Rego 编写的策略通常在文本文件中定义,在运行时由 OPA 去解析和编译,所以在数据策略中编写 Rego 条件,会转换成字符串:

OPA2

OPA3

¶ 案例

判断下当前的请求是否满足 IP 属于:10.109.201.100、10.109.201.101、10.109.201.102这三个;请求时间不在早上 5-8 点之间;并且浏览器是 Chrome 或者 Safari。下图是通过表单的方式的配置:

OPA4

我们根据这个案例,使用 Rego 进行编写,如下:

# 包声明
package play

# 如果引用了外部包,则需要使用 improt 声明
# if 是一个非默认的关键字,所以需要引用
import future.keywords.if

# 声明一个 isChrome 变量,默认值为 false,由于使用 default 进行声明,不论它是否为 true 或 false,OPA 一定会输出给用户
default isChrome = false

# 此处使用 if 关键字,它仅仅是用来提高表现力,实际是可以省略的
isChrome if {
        # input 是系统保留字,表示用户的输入,即当我们执行这条策略时,输入的数据都能够通过 input 进行获取
        # 此处判断输入数据中 env.browserType 是否为 Chrome,使用 `` 定义字符串 OPA 更为推荐的方式,也可以使用 ""
        input.env.browserType == `Chrome`
}

# 从 default 声明到当前组成一个 Rule,这个Rule中有仅有一条表达式,它返回的值会被赋予给 isChrome

# 省略 if 也是可以的;
# isSafari 没有使用 default 声明,如果不为 true 则不会被 OPA 输出给用户,我们只需要一个最终结果,所以可以省略
isSafari if {
        input.env.browserType == `Safari`
}

# 下述代码片段表述逻辑关系中的"或",即浏览器类型匹配 Chrome 或者 Safair 之一,browserTypeIsMatch 则为 true
browserTypeIsMatch if {
        isChrome
}

browserTypeIsMatch if {
        isSafari
}

ipIsMatch if {
        # 此处定义一个了集合,[_]表示对这个集合进行迭代,每次迭代的数据都会交给 temp
        temp = {`10.109.201.100`, `10.109.201.101`, `10.109.201.102`}[_]
        temp == input.env.ip
}

# 多个条件必须同时满足,即逻辑关系中的"且",则写在同一个代码片段中即可,每一行都以";"结尾,换行则可以省略
requestTimeIsMatch if {
        # 此处判断请求时间不在早上 5-8 点之间,我们将 5 点和 8 点以 0 点开始换成秒数,即为 18000 和 28800
        input.env.requestTime < 18000
}{
        input.env.requestTime > 28800
}

# 
# 防止不统一,所以我们约定每个策略都必须使用 default 声明一个名为 allow 的变量,以至于我们都能通过 API 获取到执行的结果
# 因为上面 3 条规则的逻辑关系是"且",所以在定义一个布尔类型变量,汇总最终的结果
# 因为使用 default 声明,所以 OPA 一定会返回给我们,最后判断整个条件是否满足则观察 allow 的值是否为 true 即可
default allow = false

allow if {
        browserTypeIsMatch
        ipIsMatch
        requestTimeIsMatch
}

官方提供了一个 Playgroud (opens new window),支持在线执行,整个界面窗口分为如下四块:

  • 左侧一整块是Policy窗口,在此处使用 Rego 进行编写策略
  • 右上方是Input窗口,规则需要的外部数据在此处定义,可以 JSON 或 YAML 数据格式
  • 右中间是Data窗口,如果规则需要的数据是来源于持久化数据库,我们可以为策略进行绑定其存储层接口,不过我们这里不需要,所以无需关注
  • 右下方是Output窗口,OPA 进行策略决策后的结果输出区域,在 playground 这种方式中会将全部信息都输出给我们,没有办法指定查询指定的字段值,官方提示的示例中输出为布尔值。

我们将编写好的 Rego 代码在 Playground 中去执行,如下:

OPA5

因为传入的数据都是符合条件的,所以allow为true,我们也可以试着传入不匹配的数据,看看 allow 是否为false,如下:

OPA6

OPA7

¶ 数据策略使用 Rego 语言编写条件的注意事项

  • package无需声明,由于我们开放用户自定义 Rego,防止包名相同冲突,所以由程序自行生成,用户则不需要关注,不声明即可
  • 部分鉴权 API 支持传入本次请求相关的环境参数,数据策略配置了条件,程序会将这些参数传递给 OPA,那么在编写的 Rego 条件中,则可以通过 Rego 语言的系统保留字input配合参数所属属性名进行获取,这些参数名称如下:
    • env:环境属性
      • ip(IP)
      • city(城市)
      • province(省份)
      • country(国家)
      • deviceType(设备类型)
      • systemType(系统类型)
      • browserType(浏览器类型)
      • requestDate(请求时间,格式:yyyy-mm-dd hh:mm:ss)
      • requestTime(请求时间时分秒部分总和的秒数,鉴权时会根据请求参数中的 requestDate 进行计算后额外添加此参数)

¶ 示例案例

  • 获取本次鉴权请求的 IP:input.env.ip
  • 获取本次鉴权请求的设备类型:input.env.deviceType

后期我们可能会放开更多的属性,如:用户池、应用、用户等等,获取方式类似,比如放开 user 属性,获取用户名,则可以通过 input.user.username

  • 由于OPA 提供查询策略执行结果的 API 必须传入结果中存在一个变量的变量名,所以我们约定 Rego 编写的条件,必须使用 default 关键****字定义一个布尔类型且名 allow 的变量,我们判断条件是否命中时,会向 OPA 查询该策略执行结果中allow变量的值,如果为true则表示条件命中,授权成立

¶ Rego 代码示例

为降低用户学习 Rego 成本,我们根据数据策略目前支持配置的几种条件,提供了一些常用的 Rego 代码片段示例:

  • 请求地址信息是在中国湖北省武汉市
countryIsMatch {
   input.env.country == "中国"
}

provinceIsMatch {
   input.env.province == "湖北"
}

cityIsMatch {
   input.env.city == "武汉"
}

default allow = false

allow {
   countryIsMatch
   provinceIsMatch
   cityIsMatch
}
  • 请求 IP 属于:10.109.201.100、10.109.201.101、10.109.201.102
ipIsMatch {
   temp = {`10.109.201.100`, `10.109.201.101`, `10.109.201.102`}[_]
   temp == input.env.ip
}

default allow = false

allow {
   ipIsMatch
}
  • 请求设备类型是 PC 或者 Mobile
deviceTypeIsMatch {
   input.env.deviceType == "PC"
}
{
   input.env.deviceType == "Moblie"
}

default allow = false

allow {
   deviceTypeIsMatch
}
  • 请求请求时间在早上 0-8 点之间(将 8 点以 0 点开始换成秒数,即为 28800)
requestTimeIsMatch {
   input.env.requestTime >= 0
   input.env.requestTime <= 28800
}

default allow = false

allow {
   requestTimeIsMatch
}
上一篇: 数据策略与授权 下一篇: 权限视图
  • OPA 的使用
  • 如何定义 OPA 策略
  • 数据策略使用 Rego 语言编写条件的注意事项
  • Rego 代码示例

用户身份管理

集成第三方登录
手机号闪验 (opens new window)
通用登录表单组件
自定义认证流程

企业内部管理

单点登录
多因素认证
权限管理

开发者

开发文档
框架集成
博客 (opens new window)
GitHub (opens new window)
社区用户中心 (opens new window)

公司

400 888 2106
sales@authing.cn
北京市朝阳区北辰世纪中心 B 座 16 层(总)
成都市高新区天府五街 200 号 1 号楼 B 区 4 楼 406 室(分)

京ICP备19051205号

beian京公网安备 11010802035968号

© 北京蒸汽记忆科技有限公司