概述
Greenfield Storage 通过权限模块管理权限控制。
所有数据资源(如 object、bucket、payment 账户和 group)都需要授权才能访问。这些授权规定了每个账户可以执行的操作。
一些权限示例:
- Put, List, Get, Delete, Copy, and Execute data objects;
- Create, Delete, and List buckets
- Create, Delete, ListMembers, Leave groups
- Create, Associate payment accounts
- Grant, Revoke the above permissions
这些权限既链接到数据资源,也链接到有权访问这些资源的账户或 group。group 是共享相同权限的账户集合,定义公开存储在 Greenfield 区块链上,目前是纯文本。但是,计划在未来实施利用零知识证明技术的隐私模式。
值得注意的是,无论是通过智能合约还是 EOA,都可以直接从 BSC 执行权限操作,这进一步增强了其便利性。
总体而言,权限模块的接口语义与 S3 类似。
概念
术语
- Resources: bucket、object 和 group 是 Greenfield 网络中需要授权的主要资源。这些资源通过 policy 中的 greenfield 资源名称 (GRN) 进行标识。
- Actions: Greenfield 中的每个资源都有一组可以对其执行的操作。若要指定允许或拒绝哪些操作,必须提供操作枚举值。
- Principals(主体): 可以在 policy 中标识被授予访问特定资源和操作权限的账户或 group。
- Statements: 概述了权限的具体详细信息的 Policy,包括 Effect、ActionList 和 Resources。
- Effect: 设置用户请求特定操作时的结果,可以配置为允许或拒绝。
Resource
Greenfield 操纵的主要实体是资源。bucket、object 和 group 都被视为资源,每个资源都有自己的一组子资源。
bucket 子资源由以下部分组成:
- BucketInfo:允许修改的 bucket 中的特定字段,如 IsPublic 、 ReadQuota 、 payment 账户等;
- Policy: 存储 bucket 的权限信息;
- object:存储在 bucket 中的 object;
- object 所有权:新上传的 object 所有权都会自动转移到 bucket 拥有者,不管是谁上传的。
object 子资源由以下部分组成:
- ObjectInfo:允许修改 object 中的某些字段,例如 IsPublic 等;
- Policy:存储 object 的访问权限信息。
group 子资源由以下部分组成:
- GroupInfo:允许修改的 group 内的特定字段,例如成员、用户元等;
- Policy:存储 group 的访问权限信息;
- GroupMember:Greenfield 中的任何账户都可以加入一个 group,但一个 group 不能成为另一个 group 的成员;可以设置组成员资格的过期时间,如果成员过期,权限将被撤销。
Ownership
资源所有者是指创建资源的账户。默认情况下,只有资源所有者有权访问其资源。
- 资源创建者拥有资源。
- 每个资源只有一个所有者,一旦创建资源,所有权就无法转移。
- 有一些功能允许一个账户 (approver)“批准”另一个账户创建和上传要由 approver 拥有的 object,只要它在限制范围内。
- 所有者或所有者的付款账户为资源付费。
Definitions
- 所有权权限:默认情况下,所有者拥有资源的所有权限。
- 公共或私有权限:默认情况下,资源是私有的,只有所有者才能访问资源。如果资源是公共的,则任何人都可以访问它。
- 共享权限:这些权限由权限模块管理。它通常管理谁有权访问哪些资源。
共享权限有两种类型:单账号权限和 group 权限,它们以不同的格式存储在区块链状态中。
Revoke
用户可以根据需要分配一个或多个权限。但是,当资源被删除时,即使用户没有启动删除,也应删除其关联的权限 - 这可以通过清理机制进行管理。如果有太多账户有权删除 object,则单个事务所需的处理时间可能会变得过长。
示例
假设 Greenfield 有两个账户,Bob(0x1110) 和 Alice(0x1111)。一个基本的示例方案是:
- Bob 上传了 avatar.jpg 的图片到名为“profile”的 bucket 中;
- Bob 将 avatar.jpg 的 GetObject 的操作权限授予 Alice(是通过 storage module 实现的,参见 代码),它会在权限模块的 state 中存储 key
key Prefix( ObjectPermission) | ResourceID( profile_avatar.jpg) | Address(Alice)
,参见 代码。 - 当 Alice 想要读取 avatar.jpg 时,SP 应该检查 Greenfield 区块链是否
key Prefix( ObjectPermission) | ResourceID(profile_avatar.jpg) | Address(Alice)
存在于权限状态树中,以及操作列表是否包含 GetObject。参看 代码, 这里包含大部分的检查逻辑。
让我们继续讨论更复杂的场景:
- Bob 创建了名为“profile”的 bucket;
- Bob 将该 bucket 的 PutObject 操作权限授予 Alice,将 key
0x10 | ResourceID(profile) | Address(Alice)
将放入权限状态树中; - 当 Alice 想要将 avatar.jpg 上传到该 bucket 中时,它会创建一个 PutObject 交易并将在链上执行,(实际代码中,链上执行的是 createObject 操作。);
- Greenfield 区块链需要确认 Alice 是否拥有操作权限,因此它会检查权限状态树中是否存在 key
0x10 | ResourceID(profile) | Address(Alice)
,如果存在,则获取权限信息。 代码; - 如果权限信息显示 Alice 具有 profile bucket 的 PutObject 操作权限,则她可以执行 PutObject 操作(这个操作是直接和 sp 服务进行交互的)。
另一个包含 group 的更复杂的方案:
- Bob 创建了名为“Games”的 group(tx.storage.createGroup 命令 ),并创建了一个名为“profile”的 bucket。
- Bob 将 Alice 添加到 Games group(tx.storage.updateGroupMember 命令),该 group 将被放入权限状态树中
key 0x12 | ResourceID(Games) | Address(Alice)
- Bob 将 avatar.jpg 放入 bucket 配置文件中,并将 CopyObject 操作权限授予 Games group。
- 当 Alice 想要复制 avatar.jpg(tx.storage.copy_object) . 首先,Greenfield 区块链通过
key 0x11 | ResourceID(avatar.jpg) | Address(Alice)
; 如果未命中,Greenfield 将遍历 object avatar.jpg 关联的所有 group,并通过检查(例如是否存在key 0x21 | ResourceID(group, e.g. Games)
)来检查 Alice 是否是其中一个 group 的成员,然后遍历 permissionInfo 映射,并确定 Alice 是否在有权通过键0x12| ResourceID(Games) | Address(Alice)
执行 CopyObject 操作的 group 中。
State
权限模块保留以下主要 object 的状态:
- Policy :资源的所有者账户将其指定权限授予另一个账户;
- PolicyGroup :资源的所有者账户向 group 将其指定权限授予一个 group。
这些主要 object 应主要由 ID 自动递增序列 来存储和访问。为了与 S3 object 存储兼容,每个主 object 都会维护一个附加索引。
- BucketPolicyForAccount:
0x11 | BigEndian(BucketID) | AccAddress -> BigEndian(PolicyID)
- ObjectPolicyForAccount:
0x12 | BigEndian(ObjectID) | AccAddress -> BigEndian(PolicyID)
- GroupPolicyForAccount:
0x13 | BigEndian(GroupID) | AccAddress -> BigEndian(PolicyID)
- BucketPolicyForGroup:
0x21 | BigEndian(BucketID) -> ProtoBuf(PolicyGroup)
- ObjectPolicyForGroup:
0x22 | BigEndian(ObjectID) -> ProtoBuf(PolicyGroup)
- PolicyByID:
0x31 | BigEndian(PolicyID) -> ProtoBuf(Policy)
参见 代码
总结
权限模块的的所有逻辑都是通过 keeper 对外暴露的,这些接口大多被 storage 模块使用。
命令行只对外暴露了模块参数的获取接口。
评论