The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

check-acls.pl - Git::Hooks plugin for branch/tag access control.

DESCRIPTION

This Git::Hooks plugin can act as any of the below hooks to guarantee that only allowed users can push commits and tags to specific branches.

update

This hook is invoked multiple times in the remote repository during git push, once per branch being updated, checking if the user performing the push can update the branch in question.

pre-receive

This hook is invoked once in the remote repository during git push, checking if the user performing the push can update every affected branch.

To enable it you should define the appropriate Git configuration option:

    git config --add githooks.update      check-acls.pl
    git config --add githooks.pre-receive check-acls.pl

CONFIGURATION

The plugin is configured by the following git options.

check-acls.userenv STRING

When Git is performing its chores in the server to serve a push request it's usually invoked via the SSH or a web service, which take care of the authentication procedure. These services normally make the authenticated user name available in an environment variable. You may tell this hook which environment variable it is by setting this option to the variable's name. If not set, the hook will try to get the user's name from the USER environment variable and die if it's not set.

If the user name is not directly available in an environment variable you may set this option to a code snippet by prefixing it with eval:. The code will be evaluated and its value will be used as the user name. For example, RhodeCode's (http://rhodecode.org/) up to version 1.3.6 used to pass the authenticated user name in the RHODECODE_USER environment variable. From version 1.4.0 on it stopped using this variable and started to use another variable with more information in it. Like this:

    RHODECODE_EXTRAS='{"username": "rcadmin", "scm": "git", "repository": "git_intro/hooktest", "make_lock": null, "ip": "172.16.2.251", "locked_by": [null, null], "action": "push"}'

To grok the user name from this variable, one may set this option like this:

    git config check-acls.userenv \
      'eval:(exists $ENV{RHODECODE_EXTRAS} && $ENV{RHODECODE_EXTRAS} =~ /"username":\s*"([^"]+)"/) ? $1 : undef'

check-acls.admin USERSPEC

When this hook is installed, by default no user can change any reference in the repository, unless she has an explicit allowance given by one ACL (se the check-acls.acl option below). It may be usefull to give full access to a group of admins who shouldn't be subject to the ACL specifications. You may use one or more such options to give admin access to a group of people. The value of each option is interpreted in one of these ways:

username

A username specifying a single user. The username specification must match "/^\w+$/i" and will be compared to the authenticated user's name case sensitively.

@groupname

A groupname specifying a single group. The groupname specification must follow the same rules as the username above. (Groups are specified by the githooks.groups configuration variable. See the Git::Hooks documentation to know how to specify them.)

^regex

A regex which will be matched against the authenticated user's name case-insensitively. The caret is part of the regex, meaning that it's anchored at the start of the username.

check-acls.acl ACL

The authorization specification for a repository is defined by the set of ACLs defined by this option. Each ACL specify 'who' has 'what' kind of access to which refs, by means of a string with three components separated by spaces:

    who what refs

By default, nobody has access to anything, except the above-specified admins. During an update, all the ACLs are processed in the order defined by the git config --list command. The first ACL matching the authenticated username and the affected reference name (usually a branch) defines what operations are allowed. If no ACL matches username and reference name, then the operation is denied.

The 'who' component specifies to which users this ACL gives access. It can be specified in the same three ways as was explained to the check-acls.admin option above.

The 'what' component specifies what kind of access to allow. It's specified as a string of one or more of the following opcodes:

C

Create a new ref.

R

Rewind/Rebase an existing ref. (With commit loss.)

U

Update an existing ref. (A fast-forward with no commit loss.)

D

Delete an existing ref.

You may specify that the user has no access whatsoever to the references by using a single hifen (-) as the what component.

The 'refs' component specifies which refs this ACL applies to. It can be specified in one of these formats:

^REGEXP

A regular expression anchored at the beginning of the reference name. For example, "^refs/heads", meaning every branch.

!REGEXP

A negated regular expression. For example, "!^refs/heads/master", meaning everything but the master branch.

STRING

The complete name of a reference. For example, "refs/heads/master".

The ACL specification can embed strings in the format {VAR}. These strings are substituted by the corresponding environment's variable VAR value. This interpolation ocurrs before the components are split and processed.

This is useful, for instance, if you want developers to be restricted in what they can do to oficial branches but to have complete control with their own branch namespace.

    git config check-acls.acl '^. CRUD ^refs/heads/{USER}/'
    git config check-acls.acl '^. U    ^refs/heads'

In this example, every user (^.) has complete control (CRUD) to the branches below "refs/heads/{USER}". Supposing the environment variable USER contains the user's login name during a "pre-receive" hook. For all other branches (^refs/heads) the users have only update (U) rights.

REFERENCES

This script is heavily inspired (and, in some places, derived) from the update-paranoid example hook which comes with the Git distribution (https://github.com/gitster/git/blob/b12905140a8239ac687450ad43f18b5f0bcfb62e/contrib/hooks/update-paranoid).