跳转至主要内容

深入理解 Casbin 的匹配机制

· 6 分钟阅读

本文介绍如何用 Casbin 库设计和实现 RBAC。对于具有资源层级、角色会继承权限的 SaaS 平台,Casbin 是一个高性能的选择。

RBAC简介​

RBAC 根据用户拥有的角色来限制访问。为了说明层级式 RBAC 如何工作,我们先看看 Azure 的 RBAC,再在 Casbin 中实现一个类似的模型。

Azure 的层级式 RBAC​

Azure 层级

在 Azure 中,Owner 角色可以作用于不同的范围。如果我在订阅级别拥有 Owner,那么我就是该订阅下所有资源组和资源的 Owner。如果我在资源组级别拥有 Owner,那么我就是该组中所有资源的 Owner。

下图显示了订阅级别的 Owner 权限。 Subscription Owner

查看该订阅下某个资源组的 IAM,可以看到继承来的 Owner 权限。 RG Owner

这就是 Azure 的 RBAC 的层级性。很多系统都使用类似的层级。在本教程中,我们用 Casbin 实现一个类似的模型。

Casbin 如何工作​

理解 Casbin 的组成部分(请求、策略、匹配器、效果),能让你更容易地设计和调优 RBAC 模型。

什么是ACL?​

ACL(访问控制列表) 把用户映射到操作,把操作映射到资源。

模型定义​

一个最小的 ACL 模型:

[request_definition]
r = sub, act, obj

[policy_definition]
p = sub, act, obj

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
  1. request_definition:定义请求的格式。例如 alice, write, data1 的意思是“Alice 能写 data1 吗?”
  2. policy_definition:定义策略的格式。例如策略 alice, write, data1 授予 Alice 写 data1 的权限。
  3. policy_effect:多条匹配的策略如何合并(例如 allow-override)。
  4. matchers:必须满足的条件:r.sub == p.sub && r.obj == p.obj && r.act == p.act。

在 Casbin 编辑器中试一试​

打开 Casbin 编辑器,把上面的模型粘贴到 Model 编辑框中。

在策略编辑器中粘贴以下内容:

p, alice, read, data1
p, bob, write, data2

在请求编辑器中粘贴以下内容:

alice, read, data1

结果将是:

true

ACL模型、策略和请求匹配的视觉表示​

acl

什么是RBAC?​

RBAC(基于角色的访问控制) 把用户分配到角色,角色拥有对资源的权限。请求会检查用户的角色是否允许对资源执行该操作。

模型定义​

一个简单的 RBAC 模型:

[request_definition]
r = sub, act, obj

[policy_definition]
p = sub, act, obj

[role_definition]
g = _, _
g2 = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub == p.sub && g(p.act, r.act) && r.obj == p.obj
  1. role_definition:定义图关系(例如用 g 表示角色与角色或用户与角色的关系)。匹配器用这些关系来解析角色和权限。

在 Casbin 编辑器中试一试​

打开 编辑器,粘贴上面的模型。

在策略编辑器中粘贴以下内容:

p, alice, reader, data1
p, bob, owner, data2

g, reader, read
g, owner, read
g, owner, write

在请求编辑器中粘贴以下内容:

alice, read, data1
alice, write, data1
bob, write, data2
bob, read, data2
bob, write, data1

结果将是:

true
false
true
true
false

RBAC模型、策略和请求匹配的视觉表示​

rbac

g(角色到操作)关系是一张图。在策略中它写成边,例如:

g, reader, read
g, owner, read
g, owner, write
信息

p 是普通策略(用 == 比较)。 g 是图关系。还可以用后缀添加更多:g2、g3 等。

层级式 RBAC​

在层级式 RBAC 中,有多种带继承关系的 资源类型(例如 Subscription → ResourceGroup)。订阅 sub1 可以包含资源组 rg1、rg2。同样,有订阅级的角色 / 操作和资源组级的角色 / 操作,它们之间存在继承关系。例如,订阅角色 sub-owner 可能继承到资源组角色 rg-owner:如果我在 sub1 上拥有 sub-owner,就相当于在 rg1 和 rg2 上拥有 rg-owner。

模型定义​

一个最小的层级式 RBAC 模型:

[request_definition]
r = sub, act, obj

[policy_definition]
p = sub, act, obj

[role_definition]
g = _, _
g2 = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub == p.sub && g(p.act, r.act) && g2(p.obj, r.obj)

这里 g 关联角色 / 操作,g2 关联资源(例如订阅和资源组)。

在 Casbin 编辑器中试一试​

打开 编辑器,粘贴上面的模型。

在策略编辑器中粘贴以下内容:

p, alice, sub-reader, sub1
p, bob, rg-owner, rg2

// subscription role to subscription action mapping
g, sub-reader, sub-read
g, sub-owner, sub-read
g, sub-owner, sub-write

// resourceGroup role to resourceGroup action mapping
g, rg-reader, rg-read
g, rg-owner, rg-read
g, rg-owner, rg-write

// subscription role to resourceGroup role mapping
g, sub-reader, rg-reader
g, sub-owner, rg-owner

// subscription resource to resourceGroup resource mapping
g2, sub1, rg1
g2, sub2, rg2

并在请求编辑器中粘贴以下内容:

alice, rg-read, rg1

结果将是:

true

RBAC模型、策略和请求匹配的视觉表示​

hrbac

g 边(角色 → 操作、角色 → 角色)在策略中可以写成:

// subscription role to subscription action mapping
g, sub-reader, sub-read
g, sub-owner, sub-read
g, sub-owner, sub-write

// resourceGroup role to resourceGroup action mapping
g, rg-reader, rg-read
g, rg-owner, rg-read
g, rg-owner, rg-write

// subscription role to resourceGroup role mapping
g, sub-reader, rg-reader
g, sub-owner, rg-owner

g2 边把订阅映射到资源组:

// subscription resource to resourceGroup resource mapping
g2, sub1, rg1
g2, sub2, rg2

主题匹配视觉表示​

hrbac-sub-match

操作匹配视觉表示​

hrbac-act-match

对象匹配视觉表示​

hrbac-obj-match

信息

Casbin 用所有策略来评估请求。只要至少有一条策略匹配,结果就是 true;否则为 false。

结论​

本教程展示了如何在 Casbin 中表达 ACL、RBAC 和层级式 RBAC。在后续文章中,我们会在 Spring Boot 应用中实现它,并用 Casbin 保护 API。

Comments are powered by giscus and GitHub Discussions. They load from giscus.app and GitHub only after you click the button below.