Skip to content

Commit 11c80e0

Browse files
committed
make fmt
Signed-off-by: Danny Kopping <danny@coder.com>
1 parent cb25bae commit 11c80e0

File tree

1 file changed

+87
-61
lines changed

1 file changed

+87
-61
lines changed

coderd/rbac/USAGE.md

+87-61
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,36 @@
22

33
# Overview
44

5-
> _NOTE: you should probably read [`README.md`](README.md) beforehand, but it's not essential._
5+
> _NOTE: you should probably read [`README.md`](README.md) beforehand, but it's
6+
> not essential._
67
78
## Basic structure
89

9-
RBAC is made up of nouns (the objects which are protected by RBAC rules) and verbs (actions which can be performed on
10-
nouns).<br>
11-
For example, a **workspace** (noun) can be **created** (verb), provided the requester has appropriate permissions.
10+
RBAC is made up of nouns (the objects which are protected by RBAC rules) and
11+
verbs (actions which can be performed on nouns).<br> For example, a
12+
**workspace** (noun) can be **created** (verb), provided the requester has
13+
appropriate permissions.
1214

1315
## Roles
1416

1517
We have a number of roles (some of which have legacy connotations back to v1).
1618

1719
These can be found in `coderd/rbac/roles.go`.
1820

19-
| Role | Description | Example resources (non-exhaustive) |
20-
|----------------------|--------------------------------------------------------------------|----------------------------------------------|
21-
| **owner** | Super-user, first user in Coder installation, has all* permissions | all* |
22-
| **member** | A regular user | workspaces, own details, provisioner daemons |
23-
| **auditor** | Viewer of audit log events, read-only access to a few resources | audit logs, templates, users, groups |
24-
| **templateAdmin** | Administrator of templates, read-only access to a few resources | templates, workspaces, users, groups |
25-
| **userAdmin** | Administrator of users | users, groups, role assignments |
26-
| **orgAdmin** | Like **owner**, but scoped to a single organization | _(org-level equivalent)_ |
27-
| **orgMember** | Like **member**, but scoped to a single organization | _(org-level equivalent)_ |
28-
| **orgAuditor** | Like **auditor**, but scoped to a single organization | _(org-level equivalent)_ |
29-
| **orgUserAdmin** | Like **userAdmin**, but scoped to a single organization | _(org-level equivalent)_ |
30-
| **orgTemplateAdmin** | Like **templateAdmin**, but scoped to a single organization | _(org-level equivalent)_ |
31-
32-
_* except some, which are not important to this overview_
21+
| Role | Description | Example resources (non-exhaustive) |
22+
| -------------------- | ------------------------------------------------------------------- | -------------------------------------------- |
23+
| **owner** | Super-user, first user in Coder installation, has all\* permissions | all\* |
24+
| **member** | A regular user | workspaces, own details, provisioner daemons |
25+
| **auditor** | Viewer of audit log events, read-only access to a few resources | audit logs, templates, users, groups |
26+
| **templateAdmin** | Administrator of templates, read-only access to a few resources | templates, workspaces, users, groups |
27+
| **userAdmin** | Administrator of users | users, groups, role assignments |
28+
| **orgAdmin** | Like **owner**, but scoped to a single organization | _(org-level equivalent)_ |
29+
| **orgMember** | Like **member**, but scoped to a single organization | _(org-level equivalent)_ |
30+
| **orgAuditor** | Like **auditor**, but scoped to a single organization | _(org-level equivalent)_ |
31+
| **orgUserAdmin** | Like **userAdmin**, but scoped to a single organization | _(org-level equivalent)_ |
32+
| **orgTemplateAdmin** | Like **templateAdmin**, but scoped to a single organization | _(org-level equivalent)_ |
33+
34+
_\* except some, which are not important to this overview_
3335

3436
## Actions
3537

@@ -38,7 +40,7 @@ Roles are collections of permissions (we call them _actions_).
3840
These can be found in `coderd/rbac/policy/policy.go`.
3941

4042
| Action | Description |
41-
|-------------------------|-----------------------------------------|
43+
| ----------------------- | --------------------------------------- |
4244
| **create** | Create a resource |
4345
| **read** | Read a resource |
4446
| **update** | Update a resource |
@@ -55,15 +57,19 @@ These can be found in `coderd/rbac/policy/policy.go`.
5557

5658
# Creating a new noun
5759

58-
In the following example, we're going to create a new RBAC noun for a new entity called a "frobulator" _(just some nonsense word for demonstration purposes)_.
60+
In the following example, we're going to create a new RBAC noun for a new entity
61+
called a "frobulator" _(just some nonsense word for demonstration purposes)_.
5962

60-
_Refer to https://github.com/coder/coder/pull/14055 to see a full implementation._
63+
_Refer to https://github.com/coder/coder/pull/14055 to see a full
64+
implementation._
6165

6266
## Creating a new entity
6367

64-
If you're creating a new resource which has to be owned by users of differing roles, you need to create a new RBAC resource.
68+
If you're creating a new resource which has to be owned by users of differing
69+
roles, you need to create a new RBAC resource.
6570

66-
Let's say we're adding a new table called `frobulators` (we'll use this table later):
71+
Let's say we're adding a new table called `frobulators` (we'll use this table
72+
later):
6773

6874
```sql
6975
CREATE TABLE frobulators
@@ -92,15 +98,17 @@ Let's now add our frobulator noun to `coderd/rbac/policy/policy.go`:
9298
...
9399
```
94100

95-
Entries in the `frobulators` table be created/read/updated/deleted, so we define those actions.
101+
Entries in the `frobulators` table be created/read/updated/deleted, so we define
102+
those actions.
96103

97-
`policy.go` is used to generate code in `coderd/rbac/object_gen.go`, and we can execute this by running `make gen`.
104+
`policy.go` is used to generate code in `coderd/rbac/object_gen.go`, and we can
105+
execute this by running `make gen`.
98106

99107
Now we have this change in `coderd/rbac/object_gen.go`:
100108

101109
```go
102110
...
103-
// ResourceFrobulator
111+
// ResourceFrobulator
104112
// Valid Actions
105113
// - "ActionCreate" ::
106114
// - "ActionDelete" ::
@@ -109,44 +117,48 @@ Now we have this change in `coderd/rbac/object_gen.go`:
109117
ResourceFrobulator = Object{
110118
Type: "frobulator",
111119
}
112-
...
120+
...
113121

114-
func AllResources() []Objecter {
115-
...
116-
ResourceFrobulator,
117-
...
118-
}
122+
func AllResources() []Objecter {
123+
...
124+
ResourceFrobulator,
125+
...
126+
}
119127
```
120128

121-
This creates a resource which represents this noun, and adds it to a list of all available resources.
129+
This creates a resource which represents this noun, and adds it to a list of all
130+
available resources.
122131

123132
## Role Assignment
124133

125-
In our case, we want **members** to be able to CRUD their own frobulators and we want **owners** to CRUD all members' frobulators.
126-
This is how most resources work, and the RBAC system is setup for this by default.
134+
In our case, we want **members** to be able to CRUD their own frobulators and we
135+
want **owners** to CRUD all members' frobulators. This is how most resources
136+
work, and the RBAC system is setup for this by default.
127137

128-
However, let's say we want **auditors** to have read-only access to all members' frobulators; we need to add it to `coderd/rbac/roles.go`:
138+
However, let's say we want **auditors** to have read-only access to all members'
139+
frobulators; we need to add it to `coderd/rbac/roles.go`:
129140

130141
```go
131142
func ReloadBuiltinRoles(opts *RoleOptions) {
132143
...
133144
orgAuditor: func(organizationID uuid.UUID) Role {
134145
...
135146
return Role{
136-
...
147+
...
137148
Org: map[string][]Permission{
138149
organizationID.String(): Permissions(map[string][]policy.Action{
139150
...
140151
ResourceFrobulator.Type: {policy.ActionRead},
141152
})
142-
...
153+
...
143154
...
144155
}
145156
```
146157
147158
## Testing
148159
149-
The RBAC system is configured to test all possible actions on all available resources.
160+
The RBAC system is configured to test all possible actions on all available
161+
resources.
150162
151163
Let's run the RBAC test suite:
152164
@@ -181,10 +193,13 @@ FAIL github.com/coder/coder/v2/coderd/rbac 1.314s
181193
FAIL
182194
```
183195
184-
The message `remaining permissions should be empty for type "frobulator"` indicates that we're missing tests which validate
185-
the desired actions on our new noun.
196+
The message `remaining permissions should be empty for type "frobulator"`
197+
indicates that we're missing tests which validate the desired actions on our new
198+
noun.
186199
187-
> Take a look at `coderd/rbac/roles_test.go` in the [reference PR](https://github.com/coder/coder/pull/14055) for a complete example
200+
> Take a look at `coderd/rbac/roles_test.go` in the
201+
> [reference PR](https://github.com/coder/coder/pull/14055) for a complete
202+
> example
188203
189204
Let's add a test case:
190205
@@ -218,11 +233,13 @@ func TestRolePermissions(t *testing.T) {
218233
},
219234
```
220235
221-
Note how the `FrobulatorsModify` test case is just validating the `policy.ActionCreate, policy.ActionUpdate, policy.ActionDelete` actions,
222-
and only the **orgMember**, **orgAdmin**, and **owner** can access it.
236+
Note how the `FrobulatorsModify` test case is just validating the
237+
`policy.ActionCreate, policy.ActionUpdate, policy.ActionDelete` actions, and
238+
only the **orgMember**, **orgAdmin**, and **owner** can access it.
223239
224-
Similarly, the `FrobulatorsReadOnly` test case is only validating `policy.ActionRead`, which is allowed on all of the above
225-
plus the **orgAuditor** role.
240+
Similarly, the `FrobulatorsReadOnly` test case is only validating
241+
`policy.ActionRead`, which is allowed on all of the above plus the
242+
**orgAuditor** role.
226243
227244
Now the tests pass, because we have covered all the possible scenarios:
228245
@@ -231,7 +248,8 @@ $ go test github.com/coder/coder/v2/coderd/rbac -count=1
231248
ok github.com/coder/coder/v2/coderd/rbac 1.313s
232249
```
233250
234-
When a case is not covered, you'll see an error like this (I moved the `orgAuditor` option from `true` to `false):
251+
When a case is not covered, you'll see an error like this (I moved the
252+
`orgAuditor` option from `true` to `false):
235253

236254
```bash
237255
--- FAIL: TestRolePermissions (0.79s)
@@ -246,10 +264,11 @@ FAIL github.com/coder/coder/v2/coderd/rbac 1.390s
246264
FAIL
247265
```
248266

249-
This shows you that the `org_auditor` role has `read` permissions on the frobulator, but no test case covered it.
267+
This shows you that the `org_auditor` role has `read` permissions on the
268+
frobulator, but no test case covered it.
250269

251-
**NOTE: don't just add cases which make the tests pass; consider all the way in which your resource must be used, and test
252-
all of those scenarios!**
270+
**NOTE: don't just add cases which make the tests pass; consider all the way in
271+
which your resource must be used, and test all of those scenarios!**
253272
254273
# Database authorization
255274
@@ -264,7 +283,8 @@ FROM frobulators
264283
WHERE user_id = @user_id::uuid;
265284
```
266285

267-
Once we run `make gen`, we'll find some stubbed code in `coderd/database/dbauthz/dbauthz.go`.
286+
Once we run `make gen`, we'll find some stubbed code in
287+
`coderd/database/dbauthz/dbauthz.go`.
268288
269289
```go
270290
...
@@ -287,17 +307,22 @@ func (q *querier) GetUserFrobulators(ctx context.Context, userID uuid.UUID) ([]d
287307
...
288308
```
289309

290-
This states that the `policy.ActionRead` permission is required in this query on the `ResourceFrobulator` resources,
291-
and `WithOwner(userID.String())` specifies that this user must own the resource.
310+
This states that the `policy.ActionRead` permission is required in this query on
311+
the `ResourceFrobulator` resources, and `WithOwner(userID.String())` specifies
312+
that this user must own the resource.
292313

293-
All queries are executed through `dbauthz`, and now our little frobulators are protected!
314+
All queries are executed through `dbauthz`, and now our little frobulators are
315+
protected!
294316

295317
# API authorization
296318

297-
API authorization is not strictly required because we have database authorization in place, but it's a good practice to
298-
reject requests as soon as possible when the requester is unprivileged.
319+
API authorization is not strictly required because we have database
320+
authorization in place, but it's a good practice to reject requests as soon as
321+
possible when the requester is unprivileged.
299322
300-
> Take a look at `coderd/frobulators.go` in the [reference PR](https://github.com/coder/coder/pull/14055) for a complete example
323+
> Take a look at `coderd/frobulators.go` in the
324+
> [reference PR](https://github.com/coder/coder/pull/14055) for a complete
325+
> example
301326
302327
```go
303328
...
@@ -312,7 +337,8 @@ func (api *API) listUserFrobulators(rw http.ResponseWriter, r *http.Request) {
312337
}
313338
```
314339
315-
`api.Authorize(r, policy.ActionRead, rbac.ResourceFrobulator.WithOwner(key.UserID.String()))` is specifying that we only
316-
want to permit a user to read their own frobulators. If the requester does not have this permission, we forbid the request.
317-
We're checking the user associated to the API key here because this could also be an **owner** or **orgAdmin**, and we want to
318-
permit those users.
340+
`api.Authorize(r, policy.ActionRead, rbac.ResourceFrobulator.WithOwner(key.UserID.String()))`
341+
is specifying that we only want to permit a user to read their own frobulators.
342+
If the requester does not have this permission, we forbid the request. We're
343+
checking the user associated to the API key here because this could also be an
344+
**owner** or **orgAdmin**, and we want to permit those users.

0 commit comments

Comments
 (0)