Matter 中的所有交互模型操作都必须通过访问控制机制进行验证。每当客户端设备和服务器设备想要通过读取(或订阅)属性或事件、写入属性或调用命令来进行交互时,访问控制机制必须验证客户端是否具有足够的权限来在服务器上执行操作设备。如果没有获得足够的权限,则操作无法进行并被拒绝(状态 0x7E Access Denied
)。
初始 Administer
权限由委托者通过PASE委托通道隐式获得。此隐式 Administer
权限用于在调试期间调用服务器节点上的命令。
在调试期间和之后,管理员通过读取和写入访问控制集群的结构范围 ACL
属性来管理服务器节点上结构的 ACL,该属性始终存在于服务器节点上的端点 0 上。正是这些 ACL 通过 CASE 和组消息传递来控制该服务器节点上针对结构上的主体允许或拒绝哪些交互模型操作。
数据结构
访问控制列表 (ACL) 是结构范围内的数据结构,具有以下字段:
Privilege
- View:从非代理读取或订阅数据
- Proxy View: 可以读取和观察所有内容(代理视图权限是临时的。)
- Operate: 写入操作数据并调用操作命令
- Manage: 写入配置数据并调用配置命令(例如,绑定和组集群访问)
- Administer: 写入管理数据并调用管理命令(例如,访问控制和调试集群访问)
当一个节点被授予特定权限时,它也会被隐式授予所有逻辑上较低的权限级别。下图说明了较高权限级别如何包含较低权限级别:
默认情况下,读取属性或事件需要 View
权限,写入属性或调用命令需要 Operate
权限。对于某些端点上的某些操作,集群还可能需要更严格的权限。例如,访问控制集群需要 Administer
权限来执行其所有操作。
AuthMode
身份验证模式
具有 PASE 身份验证模式的 ACL 条目不应显式添加到访问控制列表。
- 因为有一个不可见的隐式管理条目(请参阅第6.6.2.8,“访问控制集群的引导”)在 PASE 会话期间始终同等地出现在Commissionee上(但不是Commissioner)
- 由于访问控制权限授予算法通过 PASE 调试通道隐式向管理主体节点授予管理权限,因此管理员能够在调试阶段引导节点的 AccessControl 列表;这项隐含的特权授予适用于专员管理受委托人,但不能相反。
Subjects
一个包含零个、一个或多个主题标识符的列表,它们是:
- Node ID for CASE
- Group ID for Group
一个CASE subject 可能是一个CAT,它有自己的标签和版本机制。
每个CAT都是32位的,均分为标识符值及其对应的版本:
- 高 16 位分配给标识符值
- 低16位分配给版本号
当 CAT 出现在访问控制条目的主题列表中时,它应在
节点标识符的 CASE 认证标签子空间,高 32 位设置为 0xFFFF_FFFD。
请注意,此编码不能显示为操作节点 ID。 它只是一种子编码,允许访问控制条目的主题列表中的 64 位标量表示节点 ID 和 CAT。
CASE 认证 标签 示例:
• 标签标识符 0xAB12,版本 0x0003
◦ CAT 值:0xAB12_0003
◦ 在访问控制条目主题列表中显示为 0xFFFF_FFFD_AB12_0003
节点标识符 是一个 64 位数字,用于唯一标识结构上的单个节点或一组节点。节点标识符空间的分配如下表中所述:
注意:
如果没有列出任何subjects,则该ACL适用于所有采用该认证方式的subjects。
访问控制条目的主题列表可以向多个主题授予给定权限,如果身份验证模式允许,例如在 CASE 和组身份验证模式的情况下。空的主题列表应意味着每个可能的主题都采用规定的身份验证模式被授予条目对目标的特权。
访问控制条目的目标列表可以向多个目标授予给定权限。 一个空目标列表应意味着节点公开的每个端点上的每个集群都可以使用任何匹配主题的授予权限进行访问。 目标列表中的每个目标应直接通过集群 ID(在任何端点上,或仅限于特定端点)、间接通过端点 ID(该端点上的所有集群实例)或间接通过设备指定集群实例类型 ID(包含该设备类型的所有端点上的所有集群实例)。
Targets
一个列表,包含零个、一个或多个带字段的结构化条目:
- Cluster
- Endpoint
- DeviceType
所有字段都可为空,但至少必须存在一个,并且端点和设备类型字段是互斥的(只能存在这两个字段之一):
- 如果存在集群,则 ACL 仅针对该集群。
- 如果端点存在,则 ACL 仅针对该端点。
- 如果存在设备类型,则 ACL 仅针对包含该设备类型的端点(如描述符集群所报告)。
访问控制列表示例
Access Control Cluster: {
ACL: [],
Extension: []
}
扩展属性
如果存在,管理员可以使用访问控制扩展来存储与结构的访问控制条目相关的任意数据。
访问控制权限授予算法的行为就像在调试阶段通过 PASE 调试通道,我们表示受委托人(不是Commissioner)的以下隐式访问控制条目,以授予整个节点的管理权限。
Access Control Cluster: {
ACL: [
0: { // implicit entry only; does not explicitly exist!
FabricIndex: 0, // not fabric-specific
Privilege: Administer,
AuthMode: PASE,
Subjects: [],
Targets: [] // entire node
}
]
}
在调试阶段,AddNOC 命令自动创建一个访问控制条目,授予适当的 CASE 身份验证主体整个节点的管理权限。
Access Control Cluster: {
ACL: [
0: {
FabricIndex: 1,
Privilege: Administer,
AuthMode: CASE,
Subjects: [ 0xAAAA_AAAA_AAAA_AAAA ],
Targets: []
}
]
}
管理员添加一个访问控制条目,该条目授予整个节点对所有经过 CASE 身份验证的节点的查看权限。
Access Control Cluster: {
ACL: [
...
1: {
FabricIndex: 1,
Privilege: View,
AuthMode: CASE,
Subjects: [],
Targets: []
}
]
}
管理员添加一个访问控制条目,该条目授予端点 1 和 3 的“管理”权限,以授予任何可以作为组 1 成员进行身份验证的节点。
Access Control Cluster: {
ACL: [
...
2: {
FabricIndex: 1,
Privilege: Manage,
AuthMode: Group,
Subjects: [ 0x0000_0000_0000_0001 ],
Targets: [ { Endpoint: 1 }, { Endpoint: 3 } ]
}
]
}
// 仅对端点 3 上的泵配置和控制集群 (0x0202) 以及整个节点上的任何门锁集群 (0x0101) 授予相同的权限。
Access Control Cluster: {
ACL: [
...
2: {
FabricIndex: 1,
Privilege: Manage,
AuthMode: Group,
Subjects: [ 0x0000_0000_0000_0001 ],
Targets: [ { Endpoint: 1 }, { Endpoint: 3, Cluster: 0x0000_0202 }, { Cluster: 0x0000_0101 } ]
}
]
}
管理员向 CASE authenticated Nodes 0x1111_1111_1111_1111 和 0x2222_2222_2222_2222 添加一个访问控制条目,该条目授予对整个节点上包含扩展彩色光设备 (0x010D) 的所有端点的操作权限。
Access Control Cluster: {
ACL: [
...
3: {
FabricIndex: 1,
Privilege: Operate,
AuthMode: CASE,
Subjects: [ 0x1111_1111_1111_1111, 0x2222_2222_2222_2222 ],
Targets: [ { DeviceType: 0x0000_010D } ]
}
]
}
// 管理员通过添加主题为 CAT (0xFFFF_FFFD_ABCD_0001) 的条目来更新所有相关目标的 ACL,从而向五个节点授予权限。如果 CAT 标识符值 0xABCD 和版本值0x0001授予等效权限,则管理员还可以删除节点 0x2222_2222_2222_2222 显示为显式主体的条目。
// 请注意,任何 CAT 标识符值为 0xABCD 且其 NOC 中版本值为 0x0001 或更高的节点都将具有此权限。
Access Control Cluster: {
ACL: [
...
3: {
FabricIndex: 1,
Privilege: Operate,
AuthMode: CASE,
Subjects: [ 0x1111_1111_1111_1111, 0xFFFF_FFFD_ABCD_0001],
Targets: [ { DeviceType: 0x0000_010D } ]
}
]
}
iOS测试代码
// 读取ACL信息
let accessControlCluster = MTRBaseClusterAccessControl(device: device,
endpointID: NSNumber(value: 0),
queue: matterQueue)
accessControlCluster.readAttributeACL(with: nil) { val, _ in
if let val = val as? [MTRAccessControlClusterAccessControlEntryStruct] {
// do somethings
}
}
// 写ACL信息
let entry = MTRAccessControlClusterAccessControlEntryStruct()
entry.fabricIndex = NSNumber(value: fabricIndex)
entry.authMode = NSNumber(value: authMode)
entry.privilege = NSNumber(value: 3)
entry.subjects = [NSNumber(value: catIdoperate)]
entries.append(entry) // 支持写多个配置.
let accessControlCluster = MTRBaseClusterAccessControl(device: device,
endpointID: NSNumber(value: 0),
queue: matterQueue)
accessControlCluster.writeAttributeACL(withValue: accessControlEntry) { error in
// do somethings
}