|
1
|
# Administering User Capabilities (a.k.a. Permissions) |
|
2
|
|
|
3
|
Fossil includes a powerful [role-based access control system][rbac] |
|
4
|
which affects which users have which capabilities(^Some parts of the |
|
5
|
Fossil code call these “permissions” instead, but since there is [a |
|
6
|
clear and present risk of confusion](#webonly) with operating system |
|
7
|
level file permissions in this context, we avoid using that term for |
|
8
|
Fossil’s RBAC capability flags in these pages.) within a given |
|
9
|
[served][svr] Fossil repository. We call this the “caps” system for |
|
10
|
short. |
|
11
|
|
|
12
|
Fossil stores a user’s caps as an unordered string of ASCII characters, |
|
13
|
one capability per, [currently](./impl.md#choices) limited to |
|
14
|
[alphanumerics][an]. Caps are case-sensitive: “**A**” and “**a**” are |
|
15
|
different user capabilities. |
|
16
|
|
|
17
|
This is a complex topic, so some sub-topics have their own documents: |
|
18
|
|
|
19
|
1. [Login Groups][lg] |
|
20
|
2. [Implementation Details](./impl.md) |
|
21
|
3. [User Capability Reference](./ref.html) |
|
22
|
|
|
23
|
[an]: https://en.wikipedia.org/wiki/Alphanumeric |
|
24
|
[avs]: ./admin-v-setup.md |
|
25
|
[lg]: ./login-groups.md |
|
26
|
[rbac]: https://en.wikipedia.org/wiki/Role-based_access_control |
|
27
|
|
|
28
|
|
|
29
|
## <a id="ucat"></a>User Categories |
|
30
|
|
|
31
|
Before we explain individual user capabilities and their proper |
|
32
|
administration, we want to talk about an oft-overlooked and |
|
33
|
misunderstood feature of Fossil: user categories. |
|
34
|
|
|
35
|
Fossil defines four user categories. Two of these apply based on the |
|
36
|
user’s login status: **nobody** and **anonymous**. The other two act |
|
37
|
like Unix or LDAP user groups: **reader** and **developer**. Because we |
|
38
|
use the word “group” for [another purpose][lg] in Fossil, we will |
|
39
|
avoid using it that way again in this document. The correct term in |
|
40
|
Fossil is “category.” |
|
41
|
|
|
42
|
Fossil user categories give you a way to define capability sets for four |
|
43
|
hard-coded situations within the Fossil C source code. Logically |
|
44
|
speaking: |
|
45
|
|
|
46
|
> *(developer* ∨ *reader)* ≥ *anonymous* ≥ *nobody* |
|
47
|
|
|
48
|
When a user visits a [served Fossil repository][svr] via its web UI, |
|
49
|
they initially get the capabilities of the “nobody” user category. This |
|
50
|
category would be better named “everybody” because it applies whether |
|
51
|
you’re logged in or not. |
|
52
|
|
|
53
|
When a user logs in as “anonymous” via [`/login`](/help?name=/login) they |
|
54
|
get all of the “nobody” category’s caps plus those assigned to the |
|
55
|
“anonymous” user category. It would be better named “user” because it |
|
56
|
affects all logged-in users, not just those logged in via Fossil’s |
|
57
|
anonymous user feature. |
|
58
|
|
|
59
|
When a user with either the “reader” ([**u**][u]) or “developer” |
|
60
|
([**v**][v]) capability letter logs in, they get their [individual user |
|
61
|
caps](#ucap) plus those assigned to this special user category. They |
|
62
|
also get those assigned to the “anonymous” and “nobody” categories. |
|
63
|
|
|
64
|
Because “developer” users do not automatically inherit “reader” caps, |
|
65
|
it is standard practice to give both letters to your “developer” users: |
|
66
|
**uv**. You could instead just assign cap **u** to the “developer” |
|
67
|
category. |
|
68
|
|
|
69
|
Fossil shows how these capabilities apply hierarchically in the user |
|
70
|
editing screen (Admin → Users → name) with the `[N]` `[A]` `[D]` `[R]` |
|
71
|
tags next to each capability check box. If a user gets a capability from |
|
72
|
one of the user categories already assigned to it, there is no value in |
|
73
|
redundantly assigning that same cap to the user explicitly. For example, |
|
74
|
with the default **ei** cap set for the “developer” category, the cap |
|
75
|
set **ve** is redundant because **v** grants **ei**, which includes |
|
76
|
**e**. |
|
77
|
|
|
78
|
We suggest that you lean heavily on these fixed user categories when |
|
79
|
setting up new users. Ideally, your users will group neatly into one of |
|
80
|
the predefined categories, but if not, you might be able to shoehorn |
|
81
|
them into our fixed scheme. For example, the administrator of a |
|
82
|
wiki-only Fossil repo for non-developers could treat the “developer” |
|
83
|
user category as if it were called “author,” and a forum-only repo could |
|
84
|
treat the same category as if it were called “member.” |
|
85
|
|
|
86
|
There is currently no way to define custom user categories. |
|
87
|
|
|
88
|
[svr]: ../server/ |
|
89
|
|
|
90
|
|
|
91
|
## <a id="ucap"></a>Individual User Capabilities |
|
92
|
|
|
93
|
When one or more users need to be different from the basic capabilities |
|
94
|
defined in user categories, you can assign caps to individual users. You |
|
95
|
may want to have the [cap reference][ref] open when doing such work. |
|
96
|
|
|
97
|
It is useful at this time to expand on the logical |
|
98
|
expression [above](#cat), which covered only the four fixed user categories. |
|
99
|
When we bring the individual user capabilities into it, the complete |
|
100
|
expression of the way Fossil implements user power becomes: |
|
101
|
|
|
102
|
> *setup* ≥ *admin* ≥ *moderator* ≥ *(developer* ∨ *reader)* ≥ *[subscriber]* ≥ *anonymous* ≥ *nobody* |
|
103
|
|
|
104
|
The two additions at the top are clear: [setup is all-powerful][apsu], |
|
105
|
and since admin users have [all capabilities][ref] except for Setup |
|
106
|
capability, they are [subordinate only to the setup user(s)][avsp]. |
|
107
|
|
|
108
|
The moderator insertion could go anywhere from where it’s shown now down |
|
109
|
to above the “anonymous” level, depending on what other caps you give to |
|
110
|
your moderators. Also, there is not just one type of moderator: Fossil |
|
111
|
has [wiki][l], [ticket][q], and [forum][5] moderators, each |
|
112
|
independent of the others. Usually your moderators are fairly |
|
113
|
high-status users, with developer capabilities or higher, but Fossil |
|
114
|
does allow the creation of low-status moderators. |
|
115
|
|
|
116
|
The placement of “subscriber” in that hierarchy is for the |
|
117
|
sort of subscriber who has registered an account on the repository |
|
118
|
purely to [receive email alerts and announcements][7]. Users with |
|
119
|
additional caps can also be subscribers, but not all users *are* in fact |
|
120
|
subscribers, which is why we show it in square brackets. (See [Users vs |
|
121
|
Subscribers](../alerts.md#uvs).) |
|
122
|
|
|
123
|
[apsu]: ./admin-v-setup.md#apsu |
|
124
|
[avsp]: ./admin-v-setup.md#philosophy |
|
125
|
|
|
126
|
|
|
127
|
## <a id="new"></a>New Repository Defaults |
|
128
|
|
|
129
|
Fossil creates one user account in new repos, which is named after your |
|
130
|
OS user name [by default](#defuser). |
|
131
|
|
|
132
|
Fossil gives the initial repository user the [all-powerful Setup |
|
133
|
capability][apsu]. |
|
134
|
|
|
135
|
Users who visit a [served repository][svr] without logging in get the |
|
136
|
“nobody” user category’s caps which default to |
|
137
|
**[g][g][j][j][o][o][r][r][z][z]**: clone the repo, read the wiki, |
|
138
|
check-out files via the web UI, view tickets, and pull version archives. |
|
139
|
This default is suited to random passers-by on a typical FOSS project’s |
|
140
|
public web site and its code repository. |
|
141
|
|
|
142
|
Users who [prove they are not a bot][bot] by logging in — even if only |
|
143
|
as “anonymous” — get the “nobody” capability set plus |
|
144
|
**[h][h][m][m][n][n][c][c]**: see internal hyperlinks, append to |
|
145
|
existing wiki articles, file new tickets, and comment on existing |
|
146
|
tickets. We chose these additional capabilities as those we don’t want |
|
147
|
bots to have, but which a typical small FOSS project would be happy to |
|
148
|
give anonymous humans visiting the project site. |
|
149
|
|
|
150
|
The “reader” user category is typically assigned to users who want to be |
|
151
|
identified within the repository but who primarily have a passive role |
|
152
|
in the project. The default capability set on a Fossil repo adds |
|
153
|
**[k][k][p][p][t][t][w][w]** caps to those granted by “nobody” and |
|
154
|
“anonymous”. This category is not well-named, because the default caps |
|
155
|
are all about modifying repository content: edit existing wiki pages, |
|
156
|
change one’s own password, create new ticket report formats, and modify |
|
157
|
existing tickets. This category would be better named “participant”. |
|
158
|
|
|
159
|
Those in the “developer” category get the “nobody” and “anonymous” cap |
|
160
|
sets plus **[e][e][i][i]**: view |
|
161
|
sensitive user material and check in changes. |
|
162
|
|
|
163
|
[bot]: ../antibot.wiki |
|
164
|
|
|
165
|
|
|
166
|
## <a id="pvt"></a>Consequences of Taking a Repository Private |
|
167
|
|
|
168
|
When you click Admin → Security-Audit → “Take it private,” one of the |
|
169
|
things it does is set the user capabilities for the “nobody” and |
|
170
|
“anonymous” user categories to blank, so that users who haven’t logged |
|
171
|
in can’t even see your project’s home page, and the option to log in as |
|
172
|
“anonymous” isn’t even offered. Until you log in with a user name, all |
|
173
|
you see is the repository’s skin and those few UI elements that work |
|
174
|
without any user capability checks at all, such as the “Login” link. |
|
175
|
|
|
176
|
Beware: Fossil does not reassign the capabilities these users had to |
|
177
|
other users or to the “reader” or “developer” user category! All users |
|
178
|
except those with Setup capability will lose all capabilities they |
|
179
|
inherited from “nobody” and “anonymous” categories. Setup is the [lone |
|
180
|
exception][apsu]. |
|
181
|
|
|
182
|
If you will have non-Setup users in your private repo, you should parcel |
|
183
|
out some subset of the capability set the “nobody” and “anonymous” |
|
184
|
categories had to other categories or to individual users first. |
|
185
|
|
|
186
|
|
|
187
|
## <a id="read-v-clone"></a>Reading vs. Cloning |
|
188
|
|
|
189
|
Fossil has two capabilities that are often confused: |
|
190
|
[**Read**](./ref.html#o) and [**Clone**](./ref.html#g). |
|
191
|
|
|
192
|
The **Read** capability has nothing to do with reading data from a local |
|
193
|
repository, because [caps affect Fossil’s web interfaces |
|
194
|
only](#webonly). Once you’ve cloned a remote repository to your local |
|
195
|
machine, you can do any reading you want on that repository irrespective |
|
196
|
of whether your local user within that repo has <b>Read</b> capability. |
|
197
|
The repo clone is completely under your user’s power at that point, |
|
198
|
affected only by OS file permissions and such. If you need to prevent |
|
199
|
that, you want to deny **Clone** capability instead. |
|
200
|
|
|
201
|
Withholding the **Read** capability has a different effect: it |
|
202
|
prevents a web client from viewing [embedded documentation][edoc], |
|
203
|
using [the file browser](/help?name=/dir), |
|
204
|
exploring the [history](/help?name=/timeline) of check-ins, |
|
205
|
and pulling file content via the [`/artifact`](/help?name=/artifact), |
|
206
|
[`/file`](/help?name=/file), and [`/raw`](/help?name=/raw) URLs. |
|
207
|
It is common to withhold **Read** capability from low-status visitors |
|
208
|
on private or semi-private repos to prevent them from pulling individual |
|
209
|
elements of the repo over the web one at a time, as someone may do when |
|
210
|
denied the bulk **Clone** capability. |
|
211
|
|
|
212
|
[edoc]: ../embeddeddoc.wiki |
|
213
|
|
|
214
|
|
|
215
|
## <a id="defuser"></a>Default User Name |
|
216
|
|
|
217
|
By default, Fossil assumes your OS user account name is the same as the |
|
218
|
one you use in any Fossil repository. It is the [default for a new |
|
219
|
repository](#new), though you can override this with [the `--admin-user` |
|
220
|
option][auo]. Fossil has other ways of overriding this in other contexts |
|
221
|
such as the `name@` syntax in clone URLs. |
|
222
|
|
|
223
|
It’s simplest to stick with the default; a mismatch can cause problems. |
|
224
|
For example, if you clone someone else’s repo anonymously, turn off |
|
225
|
autosync, and make check-ins to that repository, they will be assigned |
|
226
|
to your OS user name by default. If you later get a login on the remote |
|
227
|
repository under a different name and sync your repo with it, your |
|
228
|
earlier “private” check-ins will get synced to the remote under your OS |
|
229
|
user name! |
|
230
|
|
|
231
|
When such problems occur, you can amend the check-in to hide the |
|
232
|
incorrect name from Fossil reports, but the original values remain in |
|
233
|
the repository [forever][shun]. It is [difficult enough][fos] to fix |
|
234
|
such problems automatically during sync that we are unlikely to ever do |
|
235
|
so. |
|
236
|
|
|
237
|
[auo]: /help?name=new |
|
238
|
[fos]: ./impl.md#filter |
|
239
|
[shun]: ../shunning.wiki |
|
240
|
|
|
241
|
|
|
242
|
|
|
243
|
## <a id="utclone"></a>Cloning the User Table |
|
244
|
|
|
245
|
When cloning over HTTP, the initial user table in the local clone is set |
|
246
|
to its “[new state:](#new)” only one user with Setup capability, named |
|
247
|
after either your OS user account, per the default above, or after the |
|
248
|
user given in the clone URL. |
|
249
|
|
|
250
|
There is one exception: if you clone as a named Setup user, you get a |
|
251
|
complete copy of the user information. This restriction keeps the user |
|
252
|
table private except for the only user allowed to make absolutely |
|
253
|
complete clones of a remote repo, such as for failover or backup |
|
254
|
purposes. Every other user’s clone is missing this and a few other |
|
255
|
items, either for information security or PII privacy reasons. |
|
256
|
|
|
257
|
When cloning with file system paths, `file://` URLs, or over SSH, you |
|
258
|
get a complete clone, including the parent repo’s complete user table. |
|
259
|
|
|
260
|
All of the above applies to [login groups][lg] as well. |
|
261
|
|
|
262
|
|
|
263
|
## <a id="webonly"></a>Caps Affect Web Interfaces Only |
|
264
|
|
|
265
|
Fossil’s user capability system only affects accesses over `http[s]://` |
|
266
|
URLs. This includes clone, sync/push/pull, the [UI pages][wp], and [the |
|
267
|
JSON API][japi]. For everything else, the user caps aren’t consulted at |
|
268
|
all. |
|
269
|
|
|
270
|
The only checks made when working directly with a local repository are |
|
271
|
the operating system’s file system permissions. This should strike you |
|
272
|
as sensible, since if you have read access to the repository file, you |
|
273
|
can do anything you want to that repo DB including giving your user’s |
|
274
|
record the [**Setup**][s] capability, after which Fossil’s user |
|
275
|
capability system is effectively bypassed. (Or, create another Setup |
|
276
|
user, with the same end effect.) If you’re objecting that you need |
|
277
|
*write* access to the DB file to achieve this, realize that you can copy |
|
278
|
a read-only file to another location, giving yourself write access to |
|
279
|
it. |
|
280
|
|
|
281
|
This is why the `fossil ui` command |
|
282
|
gives you Setup permissions within Fossil UI: it can’t usefully prevent |
|
283
|
you from doing anything through the UI since only the local file system |
|
284
|
permissions actually matter, and you can’t start `fossil ui` without |
|
285
|
having at least read access to that file. |
|
286
|
|
|
287
|
What may be more surprising to you is that this is also true when |
|
288
|
working on a *clone* done over a local file path, except that there are |
|
289
|
then two sets of file system permission checks: once to modify the |
|
290
|
working check-out’s repo clone DB file, then again on [sync][sync] with |
|
291
|
the parent DB file. The Fossil capability checks are effectively |
|
292
|
defeated because your user has [**Setup**][s] capability on both sides |
|
293
|
of the sync. Be aware that those file checks do still matter, however: |
|
294
|
Fossil requires write access to a repo DB while cloning from it, so you |
|
295
|
can’t clone from a read-only repo DB file over a local file path. |
|
296
|
|
|
297
|
Even more surprising to you may be the fact that user caps do not affect |
|
298
|
cloning and syncing over SSH! (Not unless you go [out of your way][sshfc] |
|
299
|
to patch around it, at any rate.) When you make a change to such a |
|
300
|
repository, the stock Fossil behavior is that the change first goes to the |
|
301
|
local repo clone where file system |
|
302
|
permissions are all that matter, but then upon sync, the situation is |
|
303
|
effectively the same as when the parent repo is on the local file |
|
304
|
system. The reason behind this is that if you can log into the remote |
|
305
|
system over SSH and that user has the necessary file system permissions |
|
306
|
on that remote repo DB file to allow clone and sync operations, then |
|
307
|
we’re back in the same situation as with local files: there’s no point |
|
308
|
trying to enforce the Fossil user capabilities when you can just modify |
|
309
|
the remote DB directly, so the operation proceeds unimpeded by any user |
|
310
|
capability settings on the remote repo. |
|
311
|
|
|
312
|
Where this gets confusing is that *all* Fossil syncs are done over the |
|
313
|
HTTP protocol, including those done over `file://` and `ssh://` URLs, |
|
314
|
not just those done over `http[s]://` URLs: |
|
315
|
|
|
316
|
* For `ssh://` URLs, Fossil pipes the HTTP conversation through a |
|
317
|
local SSH client to a remote instance of Fossil running the |
|
318
|
[`test-http`](/help?name=test-http) command to receive the tunneled |
|
319
|
HTTP connection. [This interface is intentionally permissionless][sxycap]. |
|
320
|
|
|
321
|
* For `file://` URLs — as opposed to plain local file paths — |
|
322
|
the “sending” Fossil instance writes its side of |
|
323
|
the HTTP conversation out to a temporary file in the same directory |
|
324
|
as the local repo clone and then calls itself on the “receiving” |
|
325
|
repository to read that same HTTP transcript file back in to apply |
|
326
|
those changes to that repository. Presumably Fossil does this |
|
327
|
instead of using a pipe to ease portability to Windows. |
|
328
|
|
|
329
|
Despite use of HTTP for these URL types, the fact remains that |
|
330
|
checks for capabilities like [**Read**][o] and [**Write**][i] within the |
|
331
|
HTTP conversation between two Fossil instances only have a useful effect |
|
332
|
when done over an `http[s]://` URL. |
|
333
|
|
|
334
|
[sshfc]: ../server/any/http-over-ssh.md |
|
335
|
[sxycap]: /file?ci=ec5efceb8aac6cb4&name=src/main.c&ln=2748-2752 |
|
336
|
|
|
337
|
|
|
338
|
## <a id="pubpg"></a>Public Pages |
|
339
|
|
|
340
|
In Admin → Access, there is an option for giving a list of [globs][glob] |
|
341
|
to name URLs which get treated as if the visitor had [the default cap |
|
342
|
set](#defcap). For example, you could take the [**Read**][o] capability |
|
343
|
away from the “nobody” user category, who has it by default, to prevent |
|
344
|
users without logins from pulling down your repository contents one |
|
345
|
artifact at a time, yet give those users the ability to read the project |
|
346
|
documentation by setting the glob to match your [embedded |
|
347
|
documentation][edoc]’s URL root. |
|
348
|
|
|
349
|
|
|
350
|
## <a id="defcap"></a>Default User Capability Set |
|
351
|
|
|
352
|
In Admin → Access, you can define a default user capability set, which |
|
353
|
is used as: |
|
354
|
|
|
355
|
1. the default caps for users newly created by an Admin or Setup user |
|
356
|
2. the default caps for self-registered users, an option in that same UI |
|
357
|
3. the effective caps for URIs considered [public pages](#pubpg) |
|
358
|
|
|
359
|
This defaults to [**Reader**][u]. |
|
360
|
|
|
361
|
|
|
362
|
<!-- add padding so anchor links always scroll ref’d section to top --> |
|
363
|
<div style="height: 75em"></div> |
|
364
|
|
|
365
|
[ref]: ./ref.html |
|
366
|
|
|
367
|
[a]: ./ref.html#a |
|
368
|
[b]: ./ref.html#b |
|
369
|
[c]: ./ref.html#c |
|
370
|
[d]: ./ref.html#d |
|
371
|
[e]: ./ref.html#e |
|
372
|
[f]: ./ref.html#f |
|
373
|
[g]: ./ref.html#g |
|
374
|
[h]: ./ref.html#h |
|
375
|
[i]: ./ref.html#i |
|
376
|
[j]: ./ref.html#j |
|
377
|
[k]: ./ref.html#k |
|
378
|
[l]: ./ref.html#l |
|
379
|
[m]: ./ref.html#m |
|
380
|
[n]: ./ref.html#n |
|
381
|
[o]: ./ref.html#o |
|
382
|
[p]: ./ref.html#p |
|
383
|
[q]: ./ref.html#q |
|
384
|
[r]: ./ref.html#r |
|
385
|
[s]: ./ref.html#s |
|
386
|
[t]: ./ref.html#t |
|
387
|
[u]: ./ref.html#u |
|
388
|
[v]: ./ref.html#v |
|
389
|
[w]: ./ref.html#w |
|
390
|
[x]: ./ref.html#x |
|
391
|
[y]: ./ref.html#y |
|
392
|
[z]: ./ref.html#z |
|
393
|
|
|
394
|
[2]: ./ref.html#2 |
|
395
|
[3]: ./ref.html#3 |
|
396
|
[4]: ./ref.html#4 |
|
397
|
[5]: ./ref.html#5 |
|
398
|
[6]: ./ref.html#6 |
|
399
|
[7]: ./ref.html#7 |
|
400
|
|
|
401
|
[glob]: https://en.wikipedia.org/wiki/Glob_(programming) |
|
402
|
[japi]: https://docs.google.com/document/d/1fXViveNhDbiXgCuE7QDXQOKeFzf2qNUkBEgiUvoqFN4/view#heading=h.6k0k5plm18p1 |
|
403
|
[sp]: ../sync.wiki |
|
404
|
[sync]: /help?name=sync |
|
405
|
[wp]: /help#webpages |
|
406
|
|