blob: 46878ab1cfca098807751bb562fcc2b669776ded [file] [log] [blame] [view]
# Access Control Guide
All Interaction Model operations in Matter must be verified by the the Access
Control mechanism.
Whenever a client device and a server device want to interact with one another
by reading (or subscribing) attributes or events, writing attributes, or
invoking commands, the Access Control mechanism must verify that the client has
sufficient privileges to perform the operation on the server device.
If no sufficient privilege is obtained, the operation cannot take place and it
is denied (status `0x7E Access Denied`).
This guide describes how the Access Control mechanism works and how it is
implemented, and provides examples of Access Control Lists (ACLs) for different
use cases.
<hr>
## Overview
The initial `Administer` privilege is obtained by the commissioner implicitly
over the PASE commissioning channel. This implicit `Administer` privilege is
used to invoke commands on the server node during commissioning.
As part of commissioning, the commissioner invokes the `AddNOC` command,
providing a `CaseAdminNode` argument. As well as commissioning the server node
onto the fabric, that command automatically installs an ACL on the server node
for `Administer` privilege using the provided `CaseAdminNode` argument as CASE
subject. The subject may be a single node, or multiple nodes (by providing a
CAT). These nodes become fabric administrators on that server node.
During and after commissioning, administrators manage ACLs for the fabric on the
server node by reading and writing the fabric-scoped `ACL` attribute of the
Access Control Cluster, which is always present on endpoint 0 on the server
node. It is these ACLs that govern which Interaction Model operations are
allowed or denied on that server node, for subjects on the fabric, via CASE and
group messaging.
<hr>
## Access Control Lists
Access Control Lists (ACLs) are fabric-scoped data structures with the following
fields:
- `Privilege`
- `AuthMode`
- `Subjects`
- `Targets`
### Privilege field
The `Privilege` can be of the following types:
- View
- Operate
- Manage
- Administer
> **Note:** An additional `ProxyView` privilege is not yet supported in the
> Matter SDK.
By default, the `View` privilege is required to read attributes or events, and
the `Operate` privilege is required to write attributes or invoke commands.
Clusters may also require stricter privileges for certain operations on certain
endpoints. For example, the Access Control Cluster requires the `Administer`
privilege for all its operations.
If applicable, the ACL grants the privilege, and all less strict privileges
subsumed by it. Therefore an ACL for `Manage` privilege will work for operations
which require `Operate` or `View` privilege (but not `Administer` privilege).
### AuthMode field
The `AuthMode`, that is authentication modes, can be as follow:
- CASE
- Group
The ACL applies only to subjects using that authentication mode.
### Subjects field
The `Subjects` field is a list containing zero, one, or more subject
identifiers, which are:
- Node ID for CASE `AuthMode`
- Group ID for Group `AuthMode`
A CASE subject may be a CAT, which has its own tag and version mechanism.
The ACL applies only to the listed subjects; if no subjects are listed, the ACL
applies to any subjects using the authentication mode.
### Targets field
The `Targets` field is a list containing zero, one, or more structured entries
with fields:
- Cluster
- Endpoint
- DeviceType
All fields are nullable, but at least one must be present, and the endpoint and
device type fields are mutually exclusive (only one of those two may be
present):
- If cluster is present, the ACL is targeted to just that cluster.
- If endpoint is present, the ACL is targeted to just that endpoint.
- If device type is present, the ACL is targeted to just endpoints which
contain that device type (as reported by the Descriptor Cluster).
> **Note:** Specifying device type in targets is not yet supported in the Matter
> SDK.
The ACL applies only to the listed targets; if no targets are listed, the ACL
applies to any targets on the server node.
<hr>
## Limitations and Restrictions
The Matter Specification states that a Matter implementation must support at
least:
- 3 ACLs per fabric
- 4 subjects per ACL
- 3 targets per ACL
There is no guarantee that an implementation supports any more than those
minimums.
In the Matter SDK, using the example access control implementation, these values
can be configured globally in `CHIPConfig.h` or per-app in
`CHIPProjectAppConfig.h` by setting:
- CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_MAX_ENTRIES_PER_FABRIC
- CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_MAX_SUBJECTS_PER_ENTRY
- CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_MAX_TARGETS_PER_ENTRY
<hr>
## Case Studies
This section provides use case examples for different ACL scenarios.
### Single Administrator
A single controller commissions a server node, providing its own CASE node ID
for the automatically installed ACL:
- Privilege: `Administer`
- AuthMode: `CASE`
- Subjects: `112233`
- Targets: (all)
The controller will be able to perform all Interaction Model operations on the
server node, since it is the administrator.
### Multiple Administrators
The commissioner provides a CAT for the automatically installed ACL:
- Privilege: `Administer`
- AuthMode: `CASE`
- Subjects: `0xFFFFFFFD00010001`
- Targets: (all)
All controllers which have the CAT as part of their CASE credentials will be
administrators for the server node.
### Client Controllers
The commissioner installs an ACL for non-administrative controllers:
- Privilege: `View`
- AuthMode: `CASE`
- Subjects: `4444`, `5555`, `6666`
- Targets: (all)
The non-administrative controllers are granted `View` privilege for the entire
server node. This doesn't mean they can view the entire server node, as some
clusters may require stricter privileges for reading attributes or events.
### Group Messaging
The commissioner installs an ACL for group messaging:
- Privilege: `Operate`
- AuthMode: `Group`
- Subjects: `123`, `456`
- Targets: `{cluster:onoff}`, `{endpoint:1}`,
`{cluster:levelcontrol,endpoint:2}`
Members of groups 123 and 456 are granted `Operate` privilege for the on/off
cluster on any endpoint, any cluster on endpoint 1, and the level control
cluster on endpoint 2.
<hr>
## Managing ACLs using CHIP-Tool
### Usage
The following sections describe the requirements for managing ACLs using the
CHIP-Tool.
#### Entire List
The Access Control Cluster's `ACL` attribute is a list.
> **Note:** Currently, list operations for single entries (append, update,
> delete) are not yet supported in the Matter SDK, so the entire list must be
> written to the attribute to change any ACL.
The write operation may employ multiple messages, making it unreliable. In any
case, ACLs are updated as they are processed, and take effect immediately.
The implication of this is that the administrator must ensure the first ACL in
the list it is writing to the `ACL` attribute is one granting itself
`Administer` privilege. Otherwise, the administrator may lose its administrative
access during the write operation.
#### Null Fields
The tool requires all fields to be provided, even if null.
Incorrect: `{"cluster": 6}`
Correct: `{"cluster": 6, "endpoint": null, "deviceType": null}`
#### Fabric Index
The `ACL` attribute is fabric-scoped, so each ACL has a fabric index.
The tool requires this field to be provided, but ignores it when performing the
actual write.
When reading ACLs, the proper fabric index is shown.
#### Enums Identifiers
The tool requires numerical values for enums and identifiers.
- Privilege values:
- View: 1
- Operate: 3
- Manage: 4
- Administer: 5
- AuthMode values:
- CASE: 2
- Group: 3
- Values for some typical clusters:
- On/Off: 6
- Level Control: 8
- Descriptor: 29
- Binding: 30
- Access Control: 31
- Basic: 40
### Examples
This section provides examples of commands and ACL output for different
operations with the CHIP-Tool.
#### Verification of the Automatically Installed ACL
During commissioning with the CHIP-Tool, an ACL that assigns Administer rights
to the commissioner is automatically installed on the commissionee. This can be
verified using the following command:
```
out/debug/standalone/chip-tool accesscontrol read acl 1 0
```
Assuming the `CaseAdminNode` value is `112233`, the ACL command output for this
case is the following:
```
Endpoint: 0 Cluster: 0x0000_001F Attribute 0x0000_0000 DataVersion: 2578401031
ACL: 1 entries
[1]: {
FabricIndex: 1
Privilege: 5
AuthMode: 2
Subjects: 1 entries
[1]: 112233
Targets: null
}
```
#### Installing a CASE ACL
The following command example requests the installation of a CASE ACL through a
write interaction:
```
out/debug/standalone/chip-tool accesscontrol write acl '[{"fabricIndex": 0, "privilege": 5, "authMode": 2, "subjects": [112233], "targets": null}, {"fabricIndex": 0, "privilege": 1, "authMode": 2, "subjects": [4444, 5555, 6666], "targets": null}]' 1 0
```
The resulting ACL command output for this case can look like the following one:
```
Endpoint: 0 Cluster: 0x0000_001F Attribute 0x0000_0000 DataVersion: 2578401034
ACL: 2 entries
[1]: {
FabricIndex: 1
Privilege: 5
AuthMode: 2
Subjects: 1 entries
[1]: 112233
Targets: null
}
[2]: {
FabricIndex: 1
Privilege: 1
AuthMode: 2
Subjects: 3 entries
[1]: 4444
[2]: 5555
[3]: 6666
Targets: null
}
```
#### Installing a Group ACL
The following command example requests the installation of a Group ACL through a
write interaction:
```
out/debug/standalone/chip-tool accesscontrol write acl '[{"fabricIndex": 0, "privilege": 5, "authMode": 2, "subjects": [112233], "targets": null}, {"fabricIndex": 0, "privilege": 1, "authMode": 2, "subjects": [4444, 5555, 6666], "targets": null}, {"fabricIndex": 0, "privilege": 3, "authMode": 3, "subjects": [123, 456], "targets": [{"cluster": 6, "endpoint": null, "deviceType": null}, {"cluster": null, "endpoint": 1, "deviceType": null}, {"cluster": 8, "endpoint": 2, "deviceType": null}]}]' 1 0
```
The resulting ACL command output for this case can look like the following one:
```
Endpoint: 0 Cluster: 0x0000_001F Attribute 0x0000_0000DataVersion: 2578401041
ACL: 3 entries
[1]: {
FabricIndex: 1
Privilege: 5
AuthMode: 2
Subjects: 1 entries
[1]: 112233
Targets: null
}
[2]: {
FabricIndex: 1
Privilege: 1
AuthMode: 2
Subjects: 3 entries
[1]: 4444
[2]: 5555
[3]: 6666
Targets: null
}
[3]: {
FabricIndex: 1
Privilege: 3
AuthMode: 3
Subjects: 2 entries
[1]: 123
[2]: 456
Targets: 3 entries
[1]: {
Cluster: 6
Endpoint: null
DeviceType: null
}
[2]: {
Cluster: null
Endpoint: 1
DeviceType: null
}
[3]: {
Cluster: 8
Endpoint: 2
DeviceType: null
}
}
```
<hr>
## Managing ACLs Using Chip-repl
### Usage
This section provides examples of commands and ACL output for different
operations with the CHIP-repl.
#### Entire List
See the important notes in the
[Managing ACLs using CHIP-Tool](#managing-acls-using-chip-tool) section, as they
also apply to the CHIP-repl.
### Null Fields
Null fields may be omitted.
This means that the following entry is acceptable:
`Target(cluster=6, endpoint=Null, deviceType=Null)`. Just as the following one:
`Target(cluster=6)`.
The above assumes Target and Null are defined at global scope, which is not
normally the case.
#### Fabric Index
The `ACL` attribute is fabric-scoped, so each ACL has a fabric index.
The CHIP-repl ignores it when performing the actual write. Because null fields
can be omitted, simply do not provide it when writing ACLs.
When reading ACLs, the proper fabric index is shown.
#### Enums and Identifiers
The CHIP-repl accepts numerical values for enums and identifiers, but it also
accepts strongly typed values:
The privileges are:
- `Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView`
- `Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kOperate`
- `Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kManage`
- `Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister`
The authentication modes are:
- `Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCASE`
- `Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kGroup`
Some typical clusters:
- Clusters.OnOff.id
- Clusters.LevelControl.id
- Clusters.Descriptor.id
- Clusters.Binding.id
- Clusters.AccessControl.id
- Clusters.BasicInformation.id
### Examples
This section provides examples of commands and ACL output for different
operations with the CHIP-repl.
#### Automatically Installed ACL
After commissioning with chip-repl, assuming `CaseAdminNode` is 1, the
automatically installed ACL is:
```
await devCtrl.ReadAttribute(1, [ (0, Clusters.AccessControl.Attributes.Acl ) ] )
```
```
{
│ 0: {
│ │ <class 'chip.clusters.Objects.AccessControl'>: {
│ │ │ <class 'chip.clusters.Attribute.DataVersion'>: 556798280,
│ │ │ <class 'chip.clusters.Objects.AccessControl.Attributes.Acl'>: [
│ │ │ │ AccessControlEntry(
│ │ │ │ │ fabricIndex=1,
│ │ │ │ │ privilege=<Privilege.kAdminister: 5>,
│ │ │ │ │ authMode=<AuthMode.kCase: 2>,
│ │ │ │ │ subjects=[
│ │ │ │ │ │ 1
│ │ │ │ │ ],
│ │ │ │ │ targets=Null
│ │ │ │ )
│ │ │ ]
│ │ }
│ }
}
```
#### Installing a CASE ACL
```
await devCtrl.WriteAttribute(1, [ (0, Clusters.AccessControl.Attributes.Acl( [
Clusters.AccessControl.Structs.AccessControlEntryStruct(
privilege = Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister,
authMode = Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase,
subjects = [ 1 ]
),
Clusters.AccessControl.Structs.AccessControlEntryStruct(
privilege = Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView,
authMode = Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase,
subjects = [ 4444, 5555, 6666 ],
),
] ) ) ] )
```
```
{
│ 0: {
│ │ <class 'chip.clusters.Objects.AccessControl'>: {
│ │ │ <class 'chip.clusters.Attribute.DataVersion'>: 556798289,
│ │ │ <class 'chip.clusters.Objects.AccessControl.Attributes.Acl'>: [
│ │ │ │ AccessControlEntry(
│ │ │ │ │ fabricIndex=1,
│ │ │ │ │ privilege=<Privilege.kAdminister: 5>,
│ │ │ │ │ authMode=<AuthMode.kCase: 2>,
│ │ │ │ │ subjects=[
│ │ │ │ │ │ 1
│ │ │ │ │ ],
│ │ │ │ │ targets=Null
│ │ │ │ ),
│ │ │ │ AccessControlEntry(
│ │ │ │ │ fabricIndex=1,
│ │ │ │ │ privilege=<Privilege.kView: 1>,
│ │ │ │ │ authMode=<AuthMode.kCase: 2>,
│ │ │ │ │ subjects=[
│ │ │ │ │ │ 4444,
│ │ │ │ │ │ 5555,
│ │ │ │ │ │ 6666
│ │ │ │ │ ],
│ │ │ │ │ targets=Null
│ │ │ │ )
│ │ │ ]
│ │ }
│ }
}
```
#### Installing a Group ACL
```
await devCtrl.WriteAttribute(1, [ (0, Clusters.AccessControl.Attributes.Acl( [
Clusters.AccessControl.Structs.AccessControlEntryStruct(
privilege = Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister,
authMode = Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase,
subjects = [ 1 ]
),
Clusters.AccessControl.Structs.AccessControlEntryStruct(
privilege = Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView,
authMode = Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kCase,
subjects = [ 4444, 5555, 6666 ],
),
Clusters.AccessControl.Structs.AccessControlEntryStruct(
privilege = Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kOperate,
authMode = Clusters.AccessControl.Enums.AccessControlEntryAuthModeEnum.kGroup,
subjects = [ 123, 456 ],
targets = [
Clusters.AccessControl.Structs.AccessControlTargetStruct(
cluster = Clusters.OnOff.id,
),
Clusters.AccessControl.Structs.AccessControlTargetStruct(
endpoint = 1,
),
Clusters.AccessControl.Structs.AccessControlTargetStruct(
cluster = Clusters.LevelControl.id,
endpoint = 2,
),
]
),
] ) ) ] )
```
```
{
│ 0: {
│ │ <class 'chip.clusters.Objects.AccessControl'>: {
│ │ │ <class 'chip.clusters.Attribute.DataVersion'>: 556798301,
│ │ │ <class 'chip.clusters.Objects.AccessControl.Attributes.Acl'>: [
│ │ │ │ AccessControlEntry(
│ │ │ │ │ fabricIndex=1,
│ │ │ │ │ privilege=<Privilege.kAdminister: 5>,
│ │ │ │ │ authMode=<AuthMode.kCase: 2>,
│ │ │ │ │ subjects=[
│ │ │ │ │ │ 1
│ │ │ │ │ ],
│ │ │ │ │ targets=Null
│ │ │ │ ),
│ │ │ │ AccessControlEntry(
│ │ │ │ │ fabricIndex=1,
│ │ │ │ │ privilege=<Privilege.kView: 1>,
│ │ │ │ │ authMode=<AuthMode.kCase: 2>,
│ │ │ │ │ subjects=[
│ │ │ │ │ │ 4444,
│ │ │ │ │ │ 5555,
│ │ │ │ │ │ 6666
│ │ │ │ │ ],
│ │ │ │ │ targets=Null
│ │ │ │ ),
│ │ │ │ AccessControlEntry(
│ │ │ │ │ fabricIndex=1,
│ │ │ │ │ privilege=<Privilege.kOperate: 3>,
│ │ │ │ │ authMode=<AuthMode.kGroup: 3>,
│ │ │ │ │ subjects=[
│ │ │ │ │ │ 123,
│ │ │ │ │ │ 456
│ │ │ │ │ ],
│ │ │ │ │ targets=[
│ │ │ │ │ │ Target(
│ │ │ │ │ │ │ cluster=6,
│ │ │ │ │ │ │ endpoint=Null,
│ │ │ │ │ │ │ deviceType=Null
│ │ │ │ │ │ ),
│ │ │ │ │ │ Target(
│ │ │ │ │ │ │ cluster=Null,
│ │ │ │ │ │ │ endpoint=1,
│ │ │ │ │ │ │ deviceType=Null
│ │ │ │ │ │ ),
│ │ │ │ │ │ Target(
│ │ │ │ │ │ │ cluster=8,
│ │ │ │ │ │ │ endpoint=2,
│ │ │ │ │ │ │ deviceType=Null
│ │ │ │ │ │ )
│ │ │ │ │ ]
│ │ │ │ )
│ │ │ ]
│ │ }
│ }
}
```