master TOC | chapter TOC | support

security, access control, and auditing

two levels of access rights checking

Gitolite has two levels of access checks. The first check is what I will call the pre-git level. At this stage, the gl-auth-command has been invoked by sshd, and it knows just three things:

Note that at this point no git program has entered the picture, and we have no way of knowing what ref (branch, tag, etc) he is trying to update, even if it is a "write" operation.

For a "read" operation to pass this check, the username (or @all users) must have read permission (i.e., R, RW, RW+, etc.) on at least one branch of the repo (or @all repos).

For a "write" operation, there is an additional restriction: lines specifying only R (read access) don't count. The user must have write access to some ref in the repo in order to pass this stage!

The second check is via a git update hook. This check only happens for write operations. By this time we know what "ref" he is trying to update, as well as the old and the new SHAs of that ref (by which we can also deduce whether it's a rewind or not). This is where the "per-branch" permissions come into play.

Each refex that allows W access (or + if this is a rewind) for this user, on this repo, is matched against the actual refname being updated. If any of the refexes match, the push succeeds. If none of them match, it fails.

Gitolite also allows "exclude" or "deny" rules. See later in this document for details.

better logging

If you have been too liberal with the permission to rewind, it has built-in logging as an emergency fallback if someone goes too far, or for audit purposes [*]. The logfile names and location are configurable, and can include the year/month/day etc in the filename for easy archival or further processing. The log file even tells you which pattern in the config file matched to allow that specific access to proceed.

[*] setting core.logAllRefUpdates true does provide a safety net against over-zealous rewinds, but it does not tell you "who". And strangely, management does not seem to share the view that "blame" is just a synonym for "annotate" ;-)]

The log lines look like this:

2009-09-19.10:24:37  +  b4e76569659939  4fb16f2a88d8b5  myrepo refs/heads/master       user2   refs/heads/master

The "+" at the start indicates a non-fast forward update, in this case from b4e76569659939 to 4fb16f2a88d8b5. So b4e76569659939 is the one to restore! Can it get easier?

The other parts of the log line are the name of the repo, the refname being updated, the user updating it, and the refex pattern (from the config file) that matched, in case you need to debug the config file itself.

delegating parts of the config file

You can now split up the config file and delegate the authority to specify access control for their own pieces. See delegation for details.