带有Casbin的RBAC,带有带有租户和层次结构的REST API

问题描述

问题

我正在尝试设置访问控制系统以访问我开发的API。资源按照以下层次结构进行组织,API遵循相同的模式 Hierarchy 并且API可以具有以下格式

/organizations/:org_id/namespaces/:ns_id

我还定义了一个全局角色列表,即org_adminorg_viewerns_adminns_viewer管理员角色具有对资源的完全控制权,查看者角色仅具有读取访问权限。我还有一个superadmin角色,可以访问所有资源

此外,我还希望具有传递性。也就是说,org_admin应该具有ns_admin及其所有子元素。 在上图中,如果Boborg_admin上有org_id=1,则Bob也是ns_adminns_id=1上的ns_id=2ns_id=3

我尝试过的

我正在使用Casbin,到目前为止,我只是在玩casbin Editor。在过去的几天里,我已经阅读了几次他们的文档,并且试图使它无法成功运行。总结

  • 我尝试了RBAC,包括多租户

  • 我尝试使用内置函数regexMatchkeyMatchkeyMatch2keyMatch3keyMatch4)来匹配我的请求,但它从未适合我的所有情况,并且regexMatch无法区分前缀org_id1之类的12

  • 我尝试了使用一个或多个组定义(g = _,_,_g = _,_g2 =_,_)的情况

  • 我在线寻找了一些解决方案,并浏览了其他论坛,但找不到解决我问题的解决方案或提示

我能够找到一个解决方案,但这并不是最佳选择。如果不指定我的org_admin用户也是ns_admin,就无法自动为其所有子命名空间创建org_adminns_admin。如果我的用户名称间的数量增加,我将需要与我的g文件中的policy.csv定义建立越来越多的关系

当前状态

型号

[request_deFinition]
r = sub,obj,act

[policy_deFinition]
p = sub,act

[role_deFinition]
g = _,_
g2 = _,_

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

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

政策

# Superadmin roles
p,role:superadmin,/*,(GET)|(POST)|(DELETE)

# Organization roles
p,role:org_admin,/organizations/:org_id,(GET)|(POST)|(DELETE)
p,/organizations/:org_id/admin,/organizations/:org_id/namespaces/:ns_id,(GET)|(POST)|(DELETE)

p,role:org_editor,/organizations/:org_id/namespaces/ns_id,role:org_viewer,GET
p,GET

# Namespace roles
p,role:ns_admin,/organizations/:org_id/namespaces/:ns_id/admin,role:ns_editor,role:ns_viewer,GET

# Groups
g2,admin,role:superadmin
# Org admins
g,alice,/organizations/1 
#g,/organizations/1/namespaces/1
g,bob,/organizations/2
g,/organizations/2/namespaces/1
# Namespace admins
g,/organizations/1/namespaces/1

g,alison,alex,/organizations/1/namespaces/2
g,bono,/organizations/2/namespaces/2
g,boonie,/organizations/2/namespaces/2

# Namespace viewers
g,/organizations/1/namespaces/3

请求和结果

# Admin requests
admin,/organizations/2,GET -> true
admin,POST -> true
admin,/organizations/1,/organizations/1/namespaces/1,/organizations/1/namespaces/2/features/1,POST -> true
# Alice requests
alice,GET -> true
alice,POST -> true
alice,/organizations/1/admin,POST -> false,should be true
alice,GET -> false
alice,GET -> true,but not because of inheritance 
# Alison requests
alison,GET -> false
alison,POST -> false
alison,DELETE -> false
alison,POST -> true
alison,/organizations/1/namespaces/2,POST -> false
# Bob requests
bob,GET -> false
bob,GET -> true
bob,/organizations/2/namespaces/1,not because of inheritance 
# Bono requests
bono,GET -> false
bono,/organizations/1/namespaces/3,POST -> false
bono,/organizations/2/namespaces/2,POST -> true
bono,GET -> true
bono,DELETE -> false
# Boonie requests
boonie,POST -> true
boonie,GET -> false
boonie,GET -> false

我能够获得我的方案权利,但是我认为应该有一个更好的方法解决此问题。 同样失败的是传递性/继承性。例如,当我定义

# Org admins
g,/organizations/1 
g,/organizations/1/namespaces/1

我希望每个在role:org_admin中拥有/organizations/1用户都可以是role:ns_admin中的/organizations/1/namespaces/1。但这不起作用,我必须在alice

中设置role:ns_admin /organizations/1/namespaces/1

其他想法

我想避免使用自定义函数,但是可能有必要实现这一目标。例如,策略p,/organizations/:org_id/*,(GET)|(POST)|(DELETE)意味着org_admin可以执行此路径下的所有操作。然后,我们将强制用户只能是某个组织的管理员,而不能是所有组织的管理员

相反,创建g = _,_ 要求我定义如下角色:role:org_admin_1role:org_admin_2等,然后将角色映射到某个路径。这也创建了很多策略,这不是必需的问题,但是与使用它们keyMatch2()函数相比,它显得相当冗长,它使您可以在/organizations/:org_id

中使用id

结论

我愿意接受任何建议。让我知道我走错了方向。我可能会误解一些概念,或者如果不使用自定义规则,我试图做的事情是不可能的。

谢谢

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)