You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: coderd/authz/README.md
+11-11Lines changed: 11 additions & 11 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,27 +4,27 @@ Package `authz` implements AuthoriZation for Coder.
4
4
5
5
## Overview
6
6
7
-
Authorization defines what **permission** an **subject** has to perform **actions** to **resources**:
7
+
Authorization defines what **permission** an **subject** has to perform **actions** to **objects**:
8
8
-**Permission** is binary: *yes* (allowed) or *no* (denied).
9
9
-**Subject** in this case is anything that implements interface `authz.Subject`.
10
10
-**Action** here is an enumerated list of actions, but we stick to `Create`, `Read`, `Update`, and `Delete` here.
11
-
-**Resource** here is anything that implements `authz.Resource`.
11
+
-**Object** here is anything that implements `authz.Object`.
12
12
13
13
## Permission Structure
14
14
15
-
A **permission** is a rule that grants or denies access for a **subject** to perform an **action** on a **resource**.
15
+
A **permission** is a rule that grants or denies access for a **subject** to perform an **action** on a **object**.
16
16
A **permission** is always applied at a given **level**:
17
17
18
-
-**site** level applies to all resources in a given Coder deployment.
19
-
-**org** level applies to all resources that have an organization owner (`org_owner`)
20
-
-**user** level applies to all resources that have an owner with the same ID as the subject.
18
+
-**site** level applies to all objects in a given Coder deployment.
19
+
-**org** level applies to all objects that have an organization owner (`org_owner`)
20
+
-**user** level applies to all objects that have an owner with the same ID as the subject.
21
21
22
22
**Permissions** at a higher **level** always override permissions at a **lower** level.
23
23
24
24
The effect of a **permission** can be:
25
25
-**positive** (allows)
26
26
-**negative** (denies)
27
-
-**abstain** (neither allows or denies, but interpreted as deny by default)
27
+
-**abstain** (neither allows or denies, not applicable)
28
28
29
29
**Negative** permissions **always** override **positive** permissions at the same level.
30
30
Both **negative** and **positive** permissions override **abstain** at the same level.
@@ -41,24 +41,24 @@ This can be represented by the following truth table, where Y represents *positi
41
41
42
42
## Permission Representation
43
43
44
-
**Permissions** are represented in string format as `<sign>?<level>.<resource>.<id>.<action>`, where:
44
+
**Permissions** are represented in string format as `<sign>?<level>.<object>.<id>.<action>`, where:
45
45
46
46
-`sign` can be either `+` or `-`. If it is omitted, sign is assumed to be `+`.
47
47
-`level` is either `*`, `site`, `org`, or `user`.
48
-
-`resource` is any valid resource type.
48
+
-`object` is any valid resource type.
49
49
-`id` is any valid UUID v4.
50
50
-`action` is `create`, `read`, `modify`, or `delete`.
51
51
52
52
## Example Permissions
53
53
54
-
-`+site.devurl.*.read`: allowed to perform the `read` action against all resources of type `devurl` in a given Coder deployment.
54
+
-`+site.*.*.read`: allowed to perform the `read` action against all objects of type `devurl` in a given Coder deployment.
55
55
-`-user.workspace.*.create`: user is not allowed to create workspaces.
56
56
57
57
## Roles
58
58
59
59
A *role* is a set of permissions. When evaluating a role's permission to form an action, all the relevant permissions for the role are combined at each level. Permissions at a higher level override permissions at a lower level.
60
60
61
-
The following table shows the per-level role evaluation logic.
61
+
The following table shows the per-level role evaluation.
62
62
Y indicates that the role provides positive permissions, N indicates the role provides negative permissions, and _ indicates the role does not provide positive or negative permissions. YN_ indicates that the value in the cell does not matter for the access result.
This approach is problematic because of the cardinality of the RBAC model.
42
+
37
43
Recall that the legacy `pkg/access/authorize`:
44
+
38
45
- Exposes 8 possible actions, 5 possible site-level roles, 4 possible org-level roles, and 24 possible resource types
39
46
- Enforces site-wide versus organization-wide permissions separately
47
+
40
48
The new authentication model must maintain backward compatibility with this model, whilst allowing additional features such as:
49
+
41
50
- User-level ownership (which means user-level permission enforcement)
42
-
-Resources shared between users (which means permissions granular down to resource IDs)
51
+
-Objects shared between users (which means permissions granular down to resource IDs)
43
52
- Custom roles
53
+
44
54
The resulting permissions model ([documented in Notion](https://www.notion.so/coderhq/Workspaces-V2-Authz-RBAC-24fd193386eb4cf79a282a2a69e8f917)) results in a large **finite** solution space in the order of **hundreds of millions**.
45
-
We want to have a high level of confidence that changes to the implementation **do not have unintended side-effects**.
46
-
This means that simply manually writing a set of test cases possibly risks errors slipping through the cracks.
55
+
56
+
We want to have a high level of confidence that changes to the implementation **do not have unintended side-effects**. This means that simply manually writing a set of test cases possibly risks errors slipping through the cracks.
57
+
47
58
Instead, we generate (almost) all possible sets of inputs to the library, and ensure that `authz.Authorize` performs as expected.
59
+
48
60
The actual investigation of the solution space is [documented in Notion](https://www.notion.so/coderhq/Authz-Exhaustive-Testing-7683ea694c6e4c12ab0124439916b13a), but the crucial take-away of that document is:
49
61
- There is a **large** but **finite** number of possible inputs to `authz.Authorize`,
50
62
- The solution space can be broken down into 9 groups, and
51
63
- Most importantly, *each group has the same expected result.*
64
+
65
+
52
66
## Testing Methodology
67
+
53
68
We group the search space into a number of groups. Each group corresponds to a set of test cases with the same expected result. Each group consists of a set of **impactful** permissions and a set of **noise** permissions.
69
+
54
70
**Impactful** permissions are the top-level permissions that are expected to override anything else, and should be the only inputs that determine the expected result.
71
+
55
72
**Noise** is simply a set of additional permissions at a lower level that *should not* be impactful.
73
+
56
74
For each group, we take the **impactful set** of permissions, and add **noise**, and combine this into a role.
75
+
57
76
We then take the *set cross-product* of the **impactful set** and the **noise**, and assert that the expected access level of that role to perform a given action.
77
+
58
78
As some of these sets are quite large, we sample some of the noise to reduce the search space.
79
+
80
+
We also perform permutation on the **objects** of the test case, explained in [Object Permutations](#object-permutations)
81
+
59
82
**Example:**
60
-
`+site:resource:abc123:create` will always override `-user:resource:*:*`, `-user:*:abc123:*`, `-org:resource:*:create`, and so on. All permutations of those sorts of noise permissions should never change the expected result.
83
+
84
+
`+site:*:*:create` will always override `-user:resource:*:*`, `-user:*:abc123:*`, `-org:resource:*:create`, and so on. All permutations of those sorts of noise permissions should never change the expected result.
85
+
86
+
61
87
## Role Permutations
88
+
62
89
Recall that we define a permission as a 4-tuple of `(level, resource_type, resource_id, action)` (for example, `(site, workspace, 123, read)`).
90
+
63
91
A `Set` is a slice of permissions. The search space of all possible permissions is too large, so instead this package allows generating more meaningful sets for testing. This is equivalent to pruning in AI problems: a technique to reduce the size of the search space by removing parts that do not have significance.
64
-
This is the final pruned search space used in authz. Each set is represented by a Y, N, or _. The leftmost set in a row that is not '_' is the impactful set. The impactful set determines the access result. All other sets are non-impactful, and should include the `<nil>` permission.
92
+
93
+
This is the final pruned search space used in authz. Each set is represented by a Y, N, or \_. The leftmost set in a row that is not '\_' is the impactful set. The impactful set determines the access result. All other sets are non-impactful, and should include the `<nil>` permission.
94
+
65
95
The resulting search space for a row is the cross product between all sets in said row. `+` indicates the union of two sets. For example, Y+_ indicates the union of all positive permissions and abstain permissions.
@@ -77,8 +108,11 @@ The resulting search space for a row is the cross product between all sets in sa
77
108
| U- |_|_|_|_| N+Y_| N |
78
109
| A+ |_|_|_|_| Y+_| Y |
79
110
| A- |_|_|_|_|_| N |
111
+
80
112
Each row in the above table corresponds to a set of role permutations.
113
+
81
114
There are 12 possible groups of role permutations:
115
+
82
116
- Case 1 (W+):
83
117
- Impactful set: positive wildcard permissions.
84
118
- Noise: positive, negative, abstain across site, org, org-member, and user levels.
@@ -127,3 +161,20 @@ There are 12 possible groups of role permutations:
127
161
- Impactful set: nil permission.
128
162
- Noise: abstain on user level.
129
163
- Expected result: deny.
164
+
165
+
166
+
## Object Permutations
167
+
168
+
Aside from the test inputs, we also perform permutations on the object. There are 9 possible permuations based on the object, and these 9 test cases all have four distinct possibilities. These are illustrated by the below table:
0 commit comments