summaryrefslogtreecommitdiff
path: root/doc/admin/000.mdwn
blob: e84c7e6f01affc5a014a9b1b8575da5b27d589e1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
---
title: Gitano Admininistration
author: Lars Wirzenius and the Gitano project
date: unversioned for now
...

**NOTA BENE:** This is very much a work in progress. Tread carefully.

# Introduction

This document describes what a "Gitano admin" needs to know. Gitano
admins are reponsible for setting the policy of a Gitano installation:
who can access it, what they can do, what they can't do, and so on.
The target audience of this document is those who are members of the
`gitano-admin` group in a Gitano installation. We assume they know how
to use Gitano as a user already, and are comfortable editing plain
text files and using git to manage files.

This document is not about installing Gitano or configuring it to work
on a system.

# Overview

Gitano admins primarily enable people to do their jobs. This involves:

* Define Gitano access control rules using Lace.
* Add and remove Gitano users.
* Helping people with their Gitano problems.
* Possibly add and remove Git repositories, unless they allow people
  to do that themselves.

Access control to Gitano is defined using a language called Lace. It
is a fairly simple textual language for expressing what actions Gitano
users can and can't do.

# Gitano admin users

Gitano recognises users based on the ssh key they use to log in. Each
user may have multiple keys, but each key may only be used by one
user.

Gitano administrators need to be in the `gitano-admin` group.
When a Gitano instance is first created by the sysadmin
(by running `gitano-setup`), as part of the process an admin user is created.
This user belongs to the `gitano-admin` group.

It is easiest if the admins have one account that they both for normal
Gitano use and for doing admin things. However, from a security point
of view, it is probably better to have a dedicated admin account for
doing admin stuff. Further, each admin should have their own admin
account so it's easier to see who did what. This requires the admins
to have multiple keys, and to configure their ssh so that the right key
is used for each account. This can be one with stanzas in
`~/.ssh/config` such as these:

    Host gitanoadmin
    Hostname git.example.com
    User git
    IdentityFile /home/foo/.ssh/gitanoadmin.key

With a stanza like this, the `Host` name need to be used instead of
the usual name for the git server:

    git clone ssh://gitanoadmin/gitano-admin.git

# User and group management

Use the commands in the table to manage user and groups. For more
detail, give Gitano the command `help user` or `help group`.

-------             --------------------------------------------------
command             description
`user`              list existing users
`user add`          create a new user
`user del`          remove a user
`group `            list existing groups
`group add`         create a new group
`group del`         remove a group
`group desciption`  set description of group
`group adduser`     add user to group
`group deluser`     remove user from group
`group addgroup`    add group to another group
`group delgroup`    remove group from group
-------             --------------------------------------------------

Typically, groups are used to bestow priviliedges to users. Gitano
admins are added to the `gitano-admin` group. A site might have a
group `devs` for all the users who are developers and thus need to be
able to push changes to source code repositories. The site might also
have a group `ops`, whose members have read-only access to the source
code repositories.

Creating a site policy such as the above is a job for that site's
Gitano admins. Gitano comes with a very simplistic policy by default.
The policy is specified (implemented) using Lace, which we'll cover soon.


# Repository management

Repositories are managed using commands in the nearby table. Use the
Gitano `help` command to get details.

-------             ---------------------------------------------------
command             description
`create`            create a new, empty repository
`destroy`           destroy a repository
`copy`              create a new repoistory by copying an existing one
`config`            inspect or set repository configurtion
-------             ---------------------------------------------------

Configuration variables for repositories are listed in a table.

-------                 ---------------------------------------------------
variable                description
`project.archived`      Whether to hide from `ls` command and CGit output by default.
`project.description`   description of repo, shown by web interface
`project.head`          where the repository HEAD points, e.g., `refs/heads/master`
`project.owner`         Gitano user who owns the repository
-------                 ---------------------------------------------------

You can set any configuration varible, but the `project.*` ones have
special meaning to Gitano.


# Lace syntax and semantics

Lace is a language to describe access control rules for Gitano.

This chapter describes Lace in some detail. It is example driven:
rather than starting from a syntax BNF and then describing the
semantics of each construct, we'll skip the formalism and go through a
series of examples, starting from a minimal ruleset ("hello, world").

## The initial ruleset

When a Gitano instance is installed and configured by the sysadmin, a
repository called `gitano-admin` is automatically created. This
repository contains administrative information for the Gitano
instance:

* Site metadata: name, output prefix.
* Which users are created in Gitano, including any metadata about them
  (name, ssh keys).
* Ditto for groups.
* Lace rulesets for access control.

The Lace ruleset is in the directory `rules` in `gitano-admin`. A
default ruleset is inserted when the Gitano instance is created. Many
Gitano sites can just use that, but it is simplistic, and so it may be
worth adjusting it for your needs.

The root of the ruleset is in `rules/core.lace`. We will have a
walkthrough later, after we first cover some of the Lace language.

## First example

The first example is really simplistic. It contains a rule to allow a
user to do anything to a repository prefixed by their username.

    define repo_is_usernamed repository prefix ${user}/
    allow "Users can do anything to repos beginning with their username" repo_is_usernamed

Lace rules are used by Gitano whenever the user tries to do anything.
Note that they only apply for access to the repositories via Gitano
(i.e., over the ssh protocol), and do not apply when access is via
other means (e.g., the git protocol itself). When they do apply,
however, they apply to everything: pulling, pushing, creating
repositories, etc.

Lace rules are evaluated from top to bottom. A rule consists of a
condition, and either allow or deny access if the condition is true.
For example, the following two rules will allow access to cats, and
deny access to dogs:

    define user_is_cat user exact cat
    define user_is_dog user exact dog
    allow "Cats are cool" user_is_cat
    deny "Dogs drool too much" user_is_dog

The `define` statements define macros to simplify the conditions.
This is useful for more complicated things. For simpler things, like
the example above, you could write the condition directly into the
allow/deny statements:

    allow "Cats are cool" [user exact cat]
    deny "Dogs drool too much" [user exact dog]

What happens if user is neiter cat nor dog? Neither condition will be
true, and so access is neither allowed nor denied by the above ruleset
snippet. Gitano would continue evaluating further rules. If no rule
triggers, Gitano uses the default, which is set with the the `default`
statement:

    default deny "The ruleset didn't provide access. Denying by default."

If a default isn't set, the opposite of the last statement is used. If
the last statement is `allow`, but didn't trigger, the default is
`deny`, and vice versa. This can be confusing, but works OK for very
short rulesets. For anything else, set an explicit default.

## Lace language summary

The Lace language consists of the following constructs:

* `allow` and `deny` statements, with conditionals.
* Boolean expressions used in allow/deny statements.
* Macro definitions for boolean expressions, for making clearer
  conditionals.
* Includes to allow a ruleset to be split into multiple files.

The allow/deny statements look like this:

    allow "Everyone can see who they are" [operation exact whoami]
    deny "No more repos" [operation exact createrepo]

In other words, the action (`allow` or `deny`), a message shown to the
user if the action is taken, and a Boolean condition that decides if
the action should be taken. In the example above, the conditions are
`operation exact whoami` and `operation exact createrepo`.
These use the predicate
`operation`, which takes two arguments:

1.  A string comparison operator

    This can be one of:

    1.  `exact` if the operand must be exactly the same as the value.
        This makes the most sense for the `operation` operator.
        `is` is an alias for `exact`.
    2.  `prefix` if the value must begin with the operand.
        `starts` and `startswith` are aliases for `prefix`.
    3.  `suffix` if the value must end with the operand.
        `ends` and `endswith` are aliases for `suffix`.
        `prefix` is often used for branch namespaces,
        and may be used for repository namespaces.
    4.  `pattern` if the value must match a lua string match expression.
    5.  `pcre` if the value must match a perl-compatible regular expression.

    Or one of the above with `!` prepended to invert the result.

2.  The operand to compare against.

In this case our condition evalueates to true
if the user is trying to do that operation.

## Predicates in conditions

Gitano defines a number of predicates to be used in conditions. See table.

Table: Gitano predicates

----------------------   -----------
`operation`              name of operation (gitano command)
`owner`                  username of repository owner
`group`                  any of the groups of invoker of gitano or target of `as`
`ref`                    the ref (branch, tag) being operated on
`user`                   username of user invoking gitano, or target of `as`
`repository`             path of repository being operated on
`start_tree`             any of the file names that are in the tree before the commit
`target_tree`            any of the file names that are in the tree after the commit
`treediff/targets`       any of the file names of changed files
`treediff/added`         any of the file names of added files
`treediff/deleted`       any of the file names of deleted files
`treediff/modified`      any of the file names of modified files
`treediff/renamed`       any of the file names of renamed files
`treediff/renamedto`     any of the file names of destinations of a rename
`treediff/kind/$FILE`    The type of object of a file named $FILE in the new version of the tree.
`treediff/oldkind/$FILE` The type of object of a file named $FILE in the old version of the tree.
`newtype`                Object type of the new tip of the ref (e.g. "tag" or "commit").
`oldtype`                Object type of the tip of the ref before the update.
`newsha`                 SHA1 Object ID of the new tip of the ref
`oldsha`                 SHA1 Object ID of the tip of the ref before the update.
`newtaggedtype`          If new tip of the ref is a tag, type of the object that is tagged.
`oldtaggedtype`          If old tip of the ref is a tag, type of the object that is tagged.
`newtaggedsha`           If new tip of the ref is a tag, object ID of the object that is tagged.
`oldtaggedsha`           If old tip of the ref is a tag, object ID of the object that is tagged.
`newsigned`              "yes" if the new tip of the ref is signed
`oldsigned`              "yes" if the old tip of the ref is signed
`config/*`               Value of the config option with "/" converted to ".".
`as_user`                username of user invoking `as otheruser`
`as_group`               any of the groups of user invoking `as otheruser`
`targetuser`             username in a user manipulation command
`targetgroup`            the group in a group manipulation command
`member`                 the user in an group manipulation command
----------------------   -----------


Predicates can be combined using the operators `anyof` and `allof`:

    allow "Mammals are cool" anyof [user exact cat] [user exact dog]

These operators are followed by a list of conditions, and the result
is true if any condition, or all conditions, respectively, are true.
`anyof` is Boolean OR, `allof` is Boolean AND.

The result of an `allow`, `deny`, `anyof` or `alloff` condition
may be negated with the boolean NOT operation (`!`):

    deny "No cats" ![user exact cat]

Predicates may also have the negation of their operation specified,
so the following is equivalent to the above.

    deny "No cats" [user !exact cat]

## Variables for conditions

Gitano defines a number of variables to be used in conditions. See
table. These provide values that predicates test. The list of values
depends on the operation being run.

Table: Gitano variables

------------ ------------------- -----------------------------------------------------------------------
operations   variable            description
all          operation           The current operation being run.
all          source              Protocol used to interact with Gitano. ("ssh" or "git").
all          user                Current Gitano user or "gitano/anonymous".
all          config/\*           Any set config key with "." replaced with "/".
all          as\_user            Username of user invoking `as otheruser`.
all          keytag              Name of SSH key user authorised with, or "" via HTTP.
most         repository          Which repository is being operated on.
most         repository/$N       Component N of the repository path when split by "/".
most         repository/basename Last component of the repository split by "/".
most         repository/dirname  Components of repository split by "/" except for the last one.
config       key                 The key being modified or inspected.
config set   value               The value to assign to the key.
user modify  targetuser          User being created, renamed, deleted or modified.
group modify targetgroup         Group being modified
group modify targetgroup/$N      Component N of group when name is split by "-".
group modify targetgroup/suffix  Last component of group when name is split by "-".
group modify targetgroup/prefix  All but the last component of group when name is split by "-".
group modify member              User or group being added or removed from `targetgroup`.
group modify member/$N           Component N of user or group when name is split by "-".
group modify member/suffix       Last component of user or group when name is split by "-".
group modify member/prefix       All but the last component of user or group when name is split by "-".
graveyard    target              Name of destination when restoring. Name of entry when purging.
keyring list keyring             Name of the keyring to be listed
keyring      keyringname         Name of keyring being manipluated for everything except `keyring list`.
ref update   ref                 Name of the ref being updated.
ref update   newtype             Object type of the new tip of the ref (e.g. "tag" or "commit").
ref update   oldtype             Object type of the tip of the ref before the update.
ref update   newsha              SHA1 Object ID of the new tip of the ref
ref update   oldsha              SHA1 Object ID of the tip of the ref before the update.
ref update   newtaggedtype       If new tip of the ref is a tag, type of the object that is tagged.
ref update   oldtaggedtype       If old tip of the ref is a tag, type of the object that is tagged.
ref update   newtaggedsha        If new tip of the ref is a tag, object ID of the object that is tagged.
ref update   oldtaggedsha        If old tip of the ref is a tag, object ID of the object that is tagged.
ref update   newsigned           "yes" if the new tip of the ref is signed
ref update   oldsigned           "yes" if the old tip of the ref is signed
------------ ------------------- -----------------------------------------------------------------------

Variables are used as interpolations for the value of a predicate.

Interpolations are written in the form `${variable}`.
If the variable is not defined then it expands to the empty string.

So a rule that permits the owner of a repository to do whatever they want is:

    define repo_is_set repository pcre .
    define is_owner config/project/owner exact ${user}
    allow "Owners may do anything to repositories they own" repo_is_set is_owner

Since `user` and `config/project/owner` are both predicates and variables
`is_owner` can be written the other way around too.

    define is_owner user exact ${config/project/owner}

The only constraint to worry about is that variables can't have multiple values.
So `group` can't be used as a variable, but can be a predicate.

If you had a config option for the contributors to a project
you would be unable to check it with:

    define is_contributor user exact ${config/project/contributors}

However it you could check for it with:

    define is_contributor config/project/contributors exact ${user}

## Include statements in rulesets

A Lace statement may include another rules file. The search path is as
follows:

* If the included filename starts with `global:` it is included from
  the adminref (`master` branch of `gitano-admin.git`), directory
  `rules`. Thus, `include global:foo.lace` means including
  `rules/foo.lace` from the adminref.

* Otherwise, without the global prefix,
  it is included from the per-project rules
  (`refs/gitano-admin` branch of the repository being operated on).

Include statements can be made conditional by adding a predicate after the path,
so you can split up your rules

    #main.lace
    include update anyof [operation exact createref] [operation exact deleteref] [operation exact updaterefnonff]  [operation exact updaterefff]

    #update.lace
    # Require fast-forward updates to refs/heads/master
    deny "master may not be rebased" [ref exact refs/heads/master] [operation exact updaterefnonff]
    # Branches must not be tags
    deny "Branches may only be commits" [ref prefix refs/heads/] [newtype exact commit]

# Backup and restore of a Gitano instance

When gitano-setup is run, the admin needs to specify a Unix user in
whose home directory the git repositories stored. In this section
we'll assume the home directory is `/home/git`.

To backup a Gitano instance, backup `/home/git`. To restore, restore
the directory.