问题描述
问题
我正在尝试设置访问控制系统以访问我开发的API。资源按照以下层次结构进行组织,API遵循相同的模式 Hierarchy 并且API可以具有以下格式
/organizations/:org_id/namespaces/:ns_id
我还定义了一个全局角色列表,即org_admin
,org_viewer
,ns_admin
,ns_viewer
。管理员角色具有对资源的完全控制权,查看者角色仅具有读取访问权限。我还有一个superadmin
角色,可以访问所有资源
此外,我还希望具有传递性。也就是说,org_admin
应该具有ns_admin
及其所有子元素。
在上图中,如果Bob
在org_admin
上有org_id=1
,则Bob
也是ns_admin
,ns_id=1
上的ns_id=2
和ns_id=3
我尝试过的
我正在使用Casbin,到目前为止,我只是在玩casbin Editor。在过去的几天里,我已经阅读了几次他们的文档,并且试图使它无法成功运行。总结
-
我尝试了RBAC,包括多租户
-
我尝试使用内置函数(
regexMatch
,keyMatch
,keyMatch2
,keyMatch3
,keyMatch4
)来匹配我的请求,但它从未适合我的所有情况,并且regexMatch
无法区分前缀org_id
和1
之类的12
。 -
我尝试了使用一个或多个组定义(
g = _,_,_
与g = _,_
,g2 =_,_
)的情况
我能够找到一个解决方案,但这并不是最佳选择。如果不指定我的org_admin
用户也是ns_admin
,就无法自动为其所有子命名空间创建org_admin
和ns_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_1
,role:org_admin_2
等,然后将角色映射到某个路径。这也创建了很多策略,这不是必需的问题,但是与使用它们keyMatch2()
函数相比,它显得相当冗长,它使您可以在/organizations/:org_id
结论
我愿意接受任何建议。让我知道我走错了方向。我可能会误解一些概念,或者如果不使用自定义规则,我试图做的事情是不可能的。
谢谢
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)