diff options
Diffstat (limited to 'git/gitaclhook')
-rwxr-xr-x | git/gitaclhook | 205 |
1 files changed, 150 insertions, 55 deletions
diff --git a/git/gitaclhook b/git/gitaclhook index f9b3d3a..dd31dd8 100755 --- a/git/gitaclhook +++ b/git/gitaclhook @@ -18,12 +18,28 @@ use strict; use File::Spec; +use Pod::Man; +use Pod::Usage; -=doc -This hook is intended to be run as an "update" hook by git. -It is called by git-receive-pack with arguments: refname old-sha1 new-sha1. +=head1 NAME -If the hooks.aclfile keyword is defined in the repository's config file, +gitaclhook - control access to git repositories + +=head1 SYNOPSIS + +B<gitaclhook> I<refname> I<old-sha1> I<new-sha1> + +B<gitaclhook --help> + +=head1 DESCRIPTION + +This program is intended to be run as an "update" hook by git. +It is called by B<git-receive-pack> with arguments: +I<refname> I<old-sha1> I<new-sha1>. + +If the B<hooks.aclfile> keyword is defined in the repository's config file, this hook will parse the file and allow or deny update depending on -its settings. If hooks.aclfile is not defined, update is allowed +its settings. If B<hooks.aclfile> is not defined, update is allowed unconditionally. +=head1 ACL FILE + The ACL file has the usual line-oriented syntax. Comments are introduced @@ -34,3 +50,7 @@ Non-empty lines introduce ACL rules. The syntax is: - VERB PROJECT USER [OP REF] +=over 4 + +I<VERB> I<PROJECT> I<USER> [I<OP> I<REF>] + +=back @@ -38,15 +58,26 @@ where brackets denote optional parts. The parts of an ACL are: -VERB Either 'allow' or 'deny', to allow or deny the operation, - correspondingly. +=over 4 + +=item I<VERB> + +Either B<allow> or B<deny>, to allow or deny the operation, correspondingly. + +=item I<PROJECT> + +The name of the project. It is obtained by removing the directory +and suffix parts of the repository pathname. Thus, if the repository +is located in B</var/gitroot/foobar.git>, then the corresponding name of +the project is B<foobar>. -PROJECT The name of the project. It is obtained by removing the directory - and suffix parts of the repository pathname. Thus, if the repository - is located in /var/gitroot/foobar.git, then the corresponding name of - the project is 'foobar'. +An asterisk matches any project name. -USER Name of the user. The word 'all' stands for any user, the word 'none' - matches no one at all. Otherwise, if this part begins with a percent - sign (%), the rest of characters aretreated as the name of the UNIX - group to check and the rule matches any user in that group. Otherwise, - the literal match is assumed. +=item I<USER> + +Name of the user. The word B<all> stands for any user, the word B<none> +matches no one at all. Otherwise, if this part begins with a percent +sign (B<%>), the rest of characters are treated as the name of the UNIX +group to check and the rule matches any user in that group. Otherwise, +the literal match is assumed. + +=back @@ -54,20 +85,45 @@ The optional parts are: -OP Requested operation codes. It is a string consisting of one or more - of the following letters (case-insensitive): - - C: create new ref - D: delete existing ref - U: fast-forward existing ref (no commit loss) - R: rewind or rebase existing ref (commit loss) - -REF Affected ref, relative to the git refs/ directory. If it begins with - a caret (^), it is treated as a Perl regular expression (with the ^ - being its part). If it ends with a /, it is treated as a prefix match, - so, e.g., "heads/baz/" matches "refs/heads/baz" and anything below. - Otherwise, it must match exactly the affected ref. - -The rule applies only if its PROJECT and USER parts match the project which is -being updated and the user who requests the update, its OP contains the opcode -of the requested operation and REF matches the affected ref. Missing REF -and/or OP are treated as a match. +=over 4 + +=item I<OP> + +Requested operation codes. It is a string consisting of one or more +of the following letters (case-insensitive): + +=over 8 + +=item B<C> + +Create new ref. + +=item B<D> + +Delete existing ref. + +=item B<U> + +Fast-forward existing ref (no commit loss). + +=item B<R> + +Rewind or rebase existing ref (commit loss). + +=back + +=item I<REF> + +Affected ref, relative to the git B<refs/> directory. If it begins with +a caret (B<^>), it is treated as a Perl regular expression (with the B<^> +being its part). If it ends with a B</>, it is treated as a prefix match, +so, e.g., B<heads/baz/> matches B<refs/heads/baz> and anything below. +Otherwise, it must match exactly the affected ref. + +=back + +=head1 RULE MATCHING + +The rule applies only if its I<PROJECT> and I<USER> parts match the project +which is being updated and the user who requests the update, its I<OP> +contains the opcode of the requested operation and I<REF> matches the affected +ref. Missing I<REF> and/or I<OP> are treated as a match. @@ -77,12 +133,12 @@ For example, assume you have the following ACL file: -allow myprog %devel U heads/master -allow myprog %pm CDUR heads/ -allow myprog %pm C ^heads/tags/v\\d+$ -allow myprog admin CDUR -deny myprog all + allow myprog %devel U heads/master + allow myprog %pm CDUR heads/ + allow myprog %pm C ^heads/tags/v\\d+$ + allow myprog admin CDUR + deny myprog all -Then the users from the 'devel' group will be able to push updates to -refs/heads/master, the users from the 'pm' group will be allowed to do -anything with refs under refs/heads and to create tags with names beginning -with 'v' and containing only digits afterwards, and the user 'admin' will +Then the users from the B<devel> group will be able to push updates to +B<refs/heads/master>, the users from the B<pm> group will be allowed to do +anything with refs under B<refs/heads> and to create tags with names beginning +with B<v> and containing only digits afterwards, and the user B<admin> will be allowed to do anything he pleases. No other users will be allowed to @@ -90,9 +146,39 @@ update that repository. -Configuration settings: +=head1 CONFIGURATION SETTINGS + +=over 4 + +=item B<hooks.aclfile> STRING + +Name of the ACL file. + +=item B<hooks.acllog> STRING + +Send log info to this file. + +=item B<hooks.acldebug> BOOL -hooks.aclfile STRING Name of the ACL file -hooks.acllog STRING Send log info to this file -hooks.acldebug BOOL Enable debugging -hooks.aclquiet BOOL Suppress diagnostics on stderr +Enable debugging. +=item B<hooks.aclquiet> BOOL + +Suppress diagnostics on stderr. + +=item B<hooks.httpd-user> STRING + +Name of the user httpd runs as. Define it if the repository can be +accessed via HTTP(S). If B<gitaclhook> is run as this user, it will +get the name of the user on behalf of which the update is performed +from the environment variable B<REMOTE_USER>. + +=back + +=head1 SEE ALSO + +B<git-receive-pack>(1). + +=head1 AUTHOR + +Sergey Poznyakoff, <gray@gno.org> + =cut @@ -133,3 +219,3 @@ sub logmsg($$;$) { -sub deny ($;$) { +sub deny($;$) { my $msg = shift; @@ -146,3 +232,3 @@ sub deny ($;$) { -sub allow ($) { +sub allow($) { logmsg("ALLOW", @@ -154,3 +240,3 @@ sub allow ($) { -sub info ($) { +sub info($) { logmsg("INFO", $_[0]); @@ -159,3 +245,3 @@ sub info ($) { -sub git_value (@) { +sub git_value(@) { my $fd; @@ -219,3 +305,3 @@ sub check_acl($$$) { - next if ($x[1] ne $project); + next if ($x[1] ne "*" and $x[1] ne $project); next unless match_user($x[2]); @@ -235,3 +321,6 @@ sub check_acl($$$) { # Sanity checks -deny "don't run this script from the command line" unless ($git_dir); +unless ($git_dir) { + pod2usage(-exitstatus => 0, -verbose => 2) if ($ref eq "--help"); + deny "try \"$0 --help\" for fore info" +} @@ -244,2 +333,8 @@ $quiet = git_value('config', 'hooks.aclquiet') unless ($debug); +my $httpdusr = git_value('config', 'hooks.httpd-user'); +if (defined($httpdusr) and $user_name eq $httpdusr) { + deny "need authenticated user" unless defined($ENV{AUTH_TYPE}); + $user_name = $ENV{REMOTE_USER}; +} + deny "need a ref name" unless $ref; |