我正在尝试通过 Ory Keto 实现以下几点:
UserA
拥有ProductA
的所有权->所有权赋予一个CRUD权利。UserB
具有角色 Admin
-> Admin
赋予对所有内容的 CRUD 权限。UserA
具有角色 KYCVerified
或者是名为 KYCVerified
的组的一部分 -> 这为用户提供了额外的权限。第 1 点描述了所有权的概念,这被描述为 RBAC 的缺点之一(source)与 Ory Keto 的当前状态:
没有所有权的概念:Dan是《你好》一文的作者 World”,因此可以更新它。
Point 2描述了一个基本通过所有权检查的角色,因为这个角色可以做任何事情。这在当前状态下应该是可能的,但不能与第 1 点结合使用。
第 3 点描述的内容与第 2 点基本相同,但这更针对我的用例。
我已经阅读了 Ory 网站上的this文章和this文章。但是,我仍然无法理解这个概念。我做了以下示例,说明我如何看待 Ory Keto 的所有权概念:
# Tenant TenantA needs to be a owner of product ProductA in order to view it
products:ProductA#view@(tenants:TenantA#owner)
# Tenant A is a owner of ProductA
tenants:ProductA#owner@TenantA
但这会导致很多规则,我什至不确定这是不是要走的路。
products:ProductA#owner@UserA
products:ProductA#crud@(products:ProductA#owner)
roles:admin#member@UserB
products:ProductA#crud@(roles:admin#member)
products:ProductA#additional_permissions@(roles:KYCVerified#member)
roles:KYCVerified#member@UserA
因为https://github.com/ory/keto/pull/877你现在可以定义全局重写:
import { Context, Namespace } from @ory/keto-config
/**
* "User" is a namespace with no additional rewrite rules defined.
*/
class User implements Namespace {}
/**
* "Role"s only have members.
*/
class Role implements Namespace {
related: {
members: User[]
}
}
/**
* "Product" is a namespace representing a product. It has some rewrites.
*/
class Product implements Namespace {
// Relations are defined and type-annotated.
related: {
/**
* "owners" are the users that are the owners of the product.
*/
owners: User[]
/**
* "admins" are the roles that are administrators of this product (potentially only one).
*/
admins: Role[]
/**
* "special_roles" are the roles a user has to be member of to gain "additional_permissions"
*/
special_roles: Role[]
}
permits = {
// this is probably three/four rewrites (create, read, update, delete) with similar rules
crud: (ctx: Context): boolean =>
this.related.owners.includes(ctx.subject) ||
this.related.admins.traverse((admin) => admin.related.members.includes(ctx.subject)),
// for the additional_permissions one has to have crud and be member of a special role
additional_permissions: (ctx: Context): boolean =>
this.permits.crud(ctx) &&
this.related.special_roles.traverse((role) => role.related.members.includes(ctx.subject))
}
}
你必须创建这些元组:
products:ProductA#owners@UserA
roles:admin#members@UserB
roles:KYCVerified#members@UserA
products:ProductA#admins@(roles:admin)
products:ProductA#additional_permissions@(roles:KYCVerified)
请注意,不可能(现在也没有计划)定义一个可以访问所有内容的
admin
组。你总是必须在对象和主题之间有某种关系才能查询/重写它。这就是有admins
和special_roles
关系的原因。