跳转至主要内容

What is RBAC? Role-Based Access Control in Casbin

What is RBAC?​

Role-based access control (RBAC) grants permissions to roles instead of to individual users, and gives each user one or more roles. To let a new employee do their job you assign them a role such as editor or billing; to change what all editors can do you change the role once.

RBAC has three parts:

  • Users: people or services that make requests.
  • Roles: named job functions, such as admin, editor or viewer.
  • Permissions: an action on a resource, such as edit on /articles.

A request is allowed when one of the user's roles holds the permission. Roles can also inherit from other roles: if editor inherits from viewer, editors get everything viewers can do. RBAC was formalized by NIST in the 1990s, and the RBAC96 family of models describes the variants: flat roles, role hierarchies and constraints. See RBAC vs. RBAC96 for how Casbin maps to them.

A minimal RBAC model and policy in Casbin:

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[role_definition]
g = _, _

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

[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
p, editor, article, edit
p, viewer, article, read

g, editor, viewer
g, alice, editor
g, bob, viewer

alice may edit and read articles (editor inherits viewer); bob may only read them.

RBAC vs ABAC: RBAC is easy to audit but cannot say "only their own records" without creating a role per record. ABAC adds conditions on attributes such as the owner or the time of day, and most applications combine both. Choosing an access control model compares ACL, RBAC, ABAC and ReBAC on one example.

Tutorials: add RBAC to a web API in Go with Gin, Node.js with Express, NestJS, Python with FastAPI, Java with Spring Boot, Rust or gRPC. You can also try the RBAC examples in the online editor.

角色定义​

[role_definition] 部分定义 RBAC 的角色(继承)关系。 Casbin 可以同时运行多套 RBAC 系统:一套用于用户(带角色继承),另一套(可选)用于资源。它们彼此独立。

这一部分是可选的;不使用 RBAC 时可以省略。

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

这里 g 和 g2 是两套角色系统;_, _ 表示每套有两端(例如用户和角色)。用户角色只用 g;资源也有角色时再加上 g2。示例:rbac_model.conf、rbac_with_resource_roles_model.conf。

用户与角色(以及资源与角色)的映射存储在策略中,例如:

p, data2_admin, data2, read
g, alice, data2_admin

也就是 alice 拥有角色 data2_admin。 Casbin 把所有名称都当作字符串(用户、资源或角色)。

在匹配器中使用角色:

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

这样只有当请求主体拥有策略中指定的角色时,请求才会被允许。

备注
  1. Casbin 只存储和评估用户与角色(以及资源与角色)的映射,不校验用户或角色是否存在。那是认证的工作。
  2. 不要让用户和角色重名(例如用户 alice 和角色 alice),因为 Casbin 无法区分它们。必要时加个前缀(例如 role_alice)。
  3. 角色继承是传递的、不限层数的:如果 A 拥有角色 B,B 拥有角色 C,那么 A 实际上拥有角色 C。
令牌名称约定
# `subject` here is for sub
[policy_definition]
p = obj, act, subject
e.SetFieldIndex("p", constant.SubjectIndex, 2) // index starts from 0
ok, err := e.DeleteUser("alice") // without SetFieldIndex, it will raise an error

角色层次​

Casbin 实现了 RBAC1 式的角色层级:如果 alice 拥有 role1,role1 拥有 role2,那么 alice 实际上拥有 role2 及其权限。

层级深度 是允许的继承层数。默认的角色管理器最大深度为 10(可配置),所以一个用户最多可以继承 10 层角色。

// NewRoleManager is the constructor for creating an instance of the
// default RoleManager implementation.
func NewRoleManager(maxHierarchyLevel int) rbac.RoleManager {
rm := RoleManager{}
rm.allRoles = &sync.Map{}
rm.maxHierarchyLevel = maxHierarchyLevel
rm.hasPattern = false

return &rm
}

区分用户和角色​

在 Casbin 中,用户和角色都是字符串。在扁平的 RBAC(没有角色层级)中,GetAllSubjects() 和 GetAllRoles() 分别返回 g 规则的左侧和右侧(通常就是用户和角色)。有层级时,同一个名称可能既作为用户又作为角色出现;如果你的应用不记录哪个是哪个,就使用命名约定(例如前缀 role::),并在解读结果时检查它。

隐式角色和权限​

通过层级继承来的角色和权限(而不只是直接分配的)称为 隐式 的。用 GetImplicitRolesForUser() 和 GetImplicitPermissionsForUser() 可以把它们包含在内;GetRolesForUser() 和 GetPermissionsForUser() 只返回直接分配的。见 GitHub #137。

RBAC 中的模式匹配​

见 带模式匹配的 RBAC。

角色管理器​

自定义角色管理见 角色管理器。

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