我有一个由两层组成的访问控制模型:Access Levels和Shared Permissions。
用户的访问级别控制您在系统中可以拥有的最大权限集,它还授予您在系统中创建顶级对象(组合、程序、项目等)的一些基本权限。系统中的其他人也可以与您共享系统中的对象(从而授予您一个或多个专门针对某个对象的权限)。如果一个对象不是由您创建或没有分配给您,那么您应该能够看到它,除非它明确与您共享。示例数据集如下所示:
"access_levels": {
"Worker": ["projects.view"],
"Planner": ["projects.create", "projects.edit", "projects.view"]
},
"users_access_level": {
"bob.jones@example.com": "Planner",
"joe.humphreys@example.com": "Worker"
},
"resource_hierarchy": {
"customer1": ["customer1"],
"project1": ["project1", "customer1"],
"project2": ["project2", "customer1"]
},
"resource_policyIDs": {
"customer1": "1",
"project1": "2",
"project2": "3",
},
"policies": {
"1": {
"permissions": ["projects.create"],
"subjects": ["users:joe.humphreys@example.com"]
},
"2": {
"permissions": ["projects.view"],
"subjects": ["users:joe.humphreys@example.com"]
},
"3": {}
}
政策看起来像这样:
package authz
default authorized = false
authorized {
input.method == "POST"
http_path = ["programs", "create"]
input.customerId == token.payload.customerId
permitted_actions(token.payload.sub, input.customerId)[_] == "programs.create"
}
subjects_resource_permissions(sub, resource) = { perm |
resource_ancestors := data.resource_hierarchy[resource]
ancestor := resource_ancestors[_]
id := data.resource_policyIDs[ancestor]
data.policies[id]["subjects"][_] == sprintf("users:%v", [sub])
perm := data.policies[id]["permissions"][_]
}
permitted_actions(sub, resource) = x {
resource_permissions := subjects_resource_permissions(sub, resource)
access_permissions := data.access_levels[data.users_access_level[sub]]
perms := {p | p := access_permissions}
x = perms & resource_permissions
}
http_path := split(trim_left(input.path, "/"), "/")
假设我创建了一个 Projects API 来管理项目资源。API 有一个列出项目的方法,该方法应该只返回用户有权查看的项目。因此,在上面的示例中,用户 'joe.humphreys@example.com' 不应该能够查看项目 2,即使他的访问级别为他提供了 'projects.view'。这是因为它没有与他共享。
如果我想使用 OPA,我如何提供一个通用模式来跨多个 API 完成此任务?对于 OPA 来说,要完成这样的事情,查询会是什么样子?换句话说,如果我想在 SQL 中强制执行此授权,那会是什么样子?
我读过这篇文章,但我很难看出它是如何适合这里的。