diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2013-06-21 12:12:08 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2013-06-21 12:12:08 +0300 |
commit | 702fcc7b2326c03e20e999dfa606cc471e6744a3 (patch) | |
tree | 6a2d35864dfc880fb05bff15cc0ffaf78ff1ad8f /gitaclhook | |
parent | b7d62f49da74058bf9e457379b6a54bf16ae432e (diff) | |
download | gitaclhook-702fcc7b2326c03e20e999dfa606cc471e6744a3.tar.gz gitaclhook-702fcc7b2326c03e20e999dfa606cc471e6744a3.tar.bz2 |
Improve gitaclhook.
Reformat and improve documentation. Display it if called with the
--help option.
Allow for * in the PROJECT field (matches any project name).
Work with http(s) transport. New configuration variable httpd-user
supplies the name of the user http server runs as.
Diffstat (limited to 'gitaclhook')
-rwxr-xr-x | gitaclhook | 169 |
1 files changed, 132 insertions, 37 deletions
@@ -16,60 +16,116 @@ 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 by the # sign and extend to the end of the physical line. Comments and empty lines are ignored. 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 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> -PROJECT The name of the project. It is obtained by removing the directory +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'. +is located in B</var/gitroot/foobar.git>, then the corresponding name of +the project is B<foobar>. -USER Name of the user. The word 'all' stands for any user, the word 'none' +An asterisk matches any project name. + +=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 (%), the rest of characters aretreated as the name of the UNIX +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 + The optional parts are: -OP Requested operation codes. It is a string consisting of one or more +=over 4 + +=item I<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) +=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> -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. +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. -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. +=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. If no rule applies, the operation is allowed. @@ -81,19 +137,49 @@ 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 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 + +Enable debugging. -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 +=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 @@ -217,7 +303,7 @@ sub check_acl($$$) { deny("malformed line", "$filename:$line") unless $#x >= 2; - next if ($x[1] ne $project); + next if ($x[1] ne "*" and $x[1] ne $project); next unless match_user($x[2]); next if ($#x >= 3 && index(uc $x[3], $op) == -1); next if ($#x == 4 && !match_ref($x[4])); @@ -233,7 +319,10 @@ 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" +} $debug = git_value('config', '--bool', 'hooks.acldebug') unless ($debug); $logfile = git_value('config', 'hooks.acllog'); @@ -242,6 +331,12 @@ if ($logfile && $logfile !~ /[>|]/) { } $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; deny "bogus ref $ref" unless $ref =~ s,^refs/,,; deny "bad old value $old" unless $old =~ /^[a-z0-9]{40}$/; |