From 1024c893e66f6059722ec6439ad1d808ebd5a995 Mon Sep 17 00:00:00 2001 From: Sitaram Chamarty Date: Thu, 19 Jul 2018 22:25:47 +0530 Subject: autoflush stdout... ...to see stdout correctly (vis-a-vis stderr) in update hook and expand-deny-messages --- src/lib/Gitolite/Hooks/Update.pm | 2 ++ src/triggers/expand-deny-messages | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/lib/Gitolite/Hooks/Update.pm b/src/lib/Gitolite/Hooks/Update.pm index 32cd6e0..2bc43a8 100644 --- a/src/lib/Gitolite/Hooks/Update.pm +++ b/src/lib/Gitolite/Hooks/Update.pm @@ -17,6 +17,8 @@ use Gitolite::Conf::Load; use strict; use warnings; +$|++; + # ---------------------------------------------------------------------- sub update { diff --git a/src/triggers/expand-deny-messages b/src/triggers/expand-deny-messages index a8b2289..8a0452b 100755 --- a/src/triggers/expand-deny-messages +++ b/src/triggers/expand-deny-messages @@ -2,6 +2,8 @@ use strict; use warnings; +$|++; + # program name: expand-deny-messages # DOCUMENTATION IS AT THE BOTTOM OF THIS FILE; PLEASE READ -- cgit v1.2.3-65-gdbad From 4bc9705d6c2a46298438e1b6f9c8bdc5792ee5ab Mon Sep 17 00:00:00 2001 From: Sitaram Chamarty Date: Sat, 21 Jul 2018 05:26:14 +0530 Subject: 'info' learns '-p' option to show only physical repos While we were meaninglessly debating (on the mailing list) the merits of showing the wild repo regexes to a *human*, someone came up with a reasonable need for an option to *not* show them so that certain automated tasks can be a wee bit simpler. Note that I still think the regexes *should* be shown to the user by default; we're just adding an option to explicitly suppress them. 15:31:59 sitaram: Thanks ! The most common use case would be for a sanity check script running on slaves that will check what repositories it has locally, and compare it with the output of info to their master. That way they can be certain all repositories are synced over properly. Second step would be to check all commit hashes of all repositories locally and their respective master. --- src/commands/info | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/commands/info b/src/commands/info index 5079cfa..b88e288 100755 --- a/src/commands/info +++ b/src/commands/info @@ -12,12 +12,13 @@ use Gitolite::Conf::Load; =for args Usage: gitolite info [-lc] [-ld] [-json] [] -List all existing repos you can access, as well as repo name patterns you can -create repos from (if any). +List all existing repos you can access, as well as repo name patterns (see +"wild repos") you have any kind of access to. '-lc' lists creators as an additional field at the end. '-ld' lists description as an additional field at the end. '-json' produce JSON output instead of normal output + '-p' limits output to physical repos only (no wild repo regexes!) The optional pattern is an unanchored regex that will limit the repos searched, in both cases. It might speed up things a little if you have more @@ -25,7 +26,7 @@ than a few thousand repos. =cut # these are globals -my ( $lc, $ld, $json, $patt ) = args(); +my ( $lc, $ld, $json, $p, $patt ) = args(); my %out; # holds info to be json'd $ENV{GL_USER} or _die "GL_USER not set"; @@ -35,8 +36,8 @@ if ($json) { print greeting(); } -print_patterns(); # repos he can create for himself -print_phy_repos(); # repos already created +print_patterns() unless $p; # repos he can create for himself +print_phy_repos(); # repos already created if ( $rc{SITE_INFO} ) { $json @@ -49,13 +50,14 @@ print JSON::to_json( \%out, { utf8 => 1, pretty => 1 } ) if $json; # ---------------------------------------------------------------------- sub args { - my ( $lc, $ld, $json, $patt ) = ( '', '', '', '' ); + my ( $lc, $ld, $json, $p, $patt ) = ( '', '', '', '' ); my $help = ''; GetOptions( 'lc' => \$lc, 'ld' => \$ld, 'json' => \$json, + 'p' => \$p, 'h' => \$help, ) or usage(); @@ -64,7 +66,7 @@ sub args { require JSON if $json; - return ( $lc, $ld, $json, $patt ); + return ( $lc, $ld, $json, $p, $patt ); } sub print_patterns { -- cgit v1.2.3-65-gdbad From 29d5bb7a92ea0a22fa35077a5c4ca6af789ce117 Mon Sep 17 00:00:00 2001 From: Sitaram Chamarty Date: Fri, 20 Jul 2018 20:04:25 +0530 Subject: VREF/NAME needs special handling in expand-deny-messages --- src/triggers/expand-deny-messages | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/triggers/expand-deny-messages b/src/triggers/expand-deny-messages index 8a0452b..107202c 100755 --- a/src/triggers/expand-deny-messages +++ b/src/triggers/expand-deny-messages @@ -49,10 +49,14 @@ _info( "Operation", _op( $a12, $aa, $oldsha, $newsha ) ); if ( $ref =~ m((^VREF/[^/]+)) ) { my $vref = $1; - my $vref_text = slurp( _which( $vref, 'x' ) ); - my $etag = '(?:help|explain|explanation)'; - $vref_text =~ m(^\s*# $etag.start\n(.*)^\s*# $etag.end\n)sm - and print STDERR "Explanation for $vref:\n$1"; + if ($ref =~ s(^VREF/NAME/)()) { + print STDERR "You're apparently not allowed to push '$ref'"; + } else { + my $vref_text = slurp( _which( $vref, 'x' ) ); + my $etag = '(?:help|explain|explanation)'; + $vref_text =~ m(^\s*# $etag.start\n(.*)^\s*# $etag.end\n)sm + and print STDERR "Explanation for $vref:\n$1"; + } } print STDERR "\n"; -- cgit v1.2.3-65-gdbad From 295c217480c463b8292aca0d884ea35391241312 Mon Sep 17 00:00:00 2001 From: Sitaram Chamarty Date: Sat, 4 Aug 2018 00:07:02 +0530 Subject: fix 'C' and 'M' tests in 'gitolite access'... MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit C was being handled incorrectly, while M was not even considered (and would behave as if MERGE_CHECK was set) thanks to Björn Kautler --- src/commands/access | 3 ++- t/access.t | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/commands/access b/src/commands/access index f02e533..8e85966 100755 --- a/src/commands/access +++ b/src/commands/access @@ -85,8 +85,9 @@ while (<>) { sub adjust_aa { my ($repo, $aa) = @_; - $aa = '+' if $aa eq 'C' and not option($repo, 'CREATE_IS_C'); + $aa = 'W' if $aa eq 'C' and not option($repo, 'CREATE_IS_C'); $aa = '+' if $aa eq 'D' and not option($repo, 'DELETE_IS_D'); + $aa = 'W' if $aa eq 'M' and not option($repo, 'MERGE_CHECK'); return $aa; } diff --git a/t/access.t b/t/access.t index c6c7b22..c3f3341 100755 --- a/t/access.t +++ b/t/access.t @@ -9,7 +9,7 @@ use Gitolite::Test; # test 'gitolite access' # ---------------------------------------------------------------------- -try "plan 216"; +try "plan 254"; confreset;confadd ' @admins = admin dev1 @@ -200,3 +200,54 @@ try " gitolite access c1 u2 +; ok gitolite access c1 u2 C; !ok "; + +confreset;confadd ' + repo foo + R = u1 + RW = u2 + RW+ = u3 + + repo bar + R = u1 + RW = u2 + RW+ = u3 + RW+CDM = u6 + +'; + +try "ADMIN_PUSH set4; !/FATAL/" or die text(); + +try " + gitolite access foo u1 +; !ok + gitolite access foo u2 +; !ok + gitolite access foo u3 +; ok + gitolite access foo u1 C; !ok + gitolite access foo u2 C; ok + gitolite access foo u3 C; ok + gitolite access foo u1 D; !ok + gitolite access foo u2 D; !ok + gitolite access foo u3 D; ok + gitolite access foo u1 M; !ok + gitolite access foo u2 M; ok + gitolite access foo u3 M; ok + + gitolite access bar u1 +; !ok + gitolite access bar u2 +; !ok + gitolite access bar u3 +; ok + gitolite access bar u1 C; !ok + gitolite access bar u2 C; !ok + gitolite access bar u3 C; !ok + gitolite access bar u1 D; !ok + gitolite access bar u2 D; !ok + gitolite access bar u3 D; !ok + gitolite access bar u1 M; !ok + gitolite access bar u2 M; !ok + gitolite access bar u3 M; !ok + + gitolite access bar u6 R; ok + gitolite access bar u6 W; ok + gitolite access bar u6 +; ok + gitolite access bar u6 C; ok + gitolite access bar u6 D; ok + gitolite access bar u6 M; ok +"; -- cgit v1.2.3-65-gdbad From b4c4bdc2b0e8727c9aabc692f74f0e5bb3135665 Mon Sep 17 00:00:00 2001 From: Sitaram Chamarty Date: Tue, 21 Aug 2018 01:04:11 +0530 Subject: access: fix minor typo in pattern name used --- src/commands/access | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/access b/src/commands/access index 8e85966..d354f4d 100755 --- a/src/commands/access +++ b/src/commands/access @@ -51,7 +51,7 @@ $ref ||= 'any'; # fq the ref if needed $ref =~ s(^)(refs/heads/) if $ref and $ref ne 'any' and $ref !~ m(^(refs|VREF)/); _die "invalid perm" if not( $aa and $aa =~ /^(R|W|\+|C|D|M|\^C)$/ ); -_die "invalid ref name" if not( $ref and $ref =~ $REPONAME_PATT ); +_die "invalid ref name" if not( $ref and $ref =~ $REF_OR_FILENAME_PATT ); my $ret = ''; -- cgit v1.2.3-65-gdbad From 91ce361528c905be44b8ad6aa74db9acf5638d54 Mon Sep 17 00:00:00 2001 From: Sitaram Chamarty Date: Sun, 26 Aug 2018 10:06:03 +0530 Subject: access: fallthru in VREFs needs fixing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Björn Kautler pointed out that for VREFs suffering fallthru, the interpretation of the result of access would be wrong. Initially, I was reluctant to make that adjustment here. The 'access' command is meant to be just a shell entry point for the access() function, nothing more, so bringing in adjustments that occur elsewhere in gitolite would not be right. But it makes automated testing for VREF rules more difficult (and VREFs are already hard enough for most people to understand), so I caved. Hopefully this won't turn into a slippery slope... --- src/commands/access | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/commands/access b/src/commands/access index d354f4d..7d4a5b9 100755 --- a/src/commands/access +++ b/src/commands/access @@ -61,6 +61,9 @@ if ( $repo ne '%' and $user ne '%' ) { show($ret) if $s; + # adjust for fallthru in VREFs + $ret =~ s/DENIED by fallthru/allowed by fallthru/ if $ref =~ m(^VREF/); + if ( $ret =~ /DENIED/ ) { print "$ret\n" unless $q; exit 1; @@ -104,7 +107,7 @@ sub show { p => skipped due to perm (W, +, etc) not matching, D => explicitly denied, A => explicitly allowed, - F => denied due to fallthru (no rules matched) + F => fallthru; access denied for normal refs, allowed for VREFs "; -- cgit v1.2.3-65-gdbad From dc13dfca8fdae5634bb0865f7e9822d2a268ed59 Mon Sep 17 00:00:00 2001 From: Sitaram Chamarty Date: Sat, 8 Sep 2018 15:38:41 +0530 Subject: prevent access to repos which are in the process of bring migrated MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Björn Kautler pointed out that, when a repo is being migrated into gitolite as per the documentation [1], there is a gap between the actual move of the repo and the rest of the process where a user can gain read or write access to the repo, which he would *not* have had after the completion of the process. My first thought was to document this, and advise people to use the 'writable' command to disable writes, but there is nothing as simple and painless to prevent reads. (On the plus side, this kind of racy read access can only happen if the conf is using the "deny-rules" option to restrict reads; without that, it makes no difference -- i.e., he gets no access that he would not have got later anyway). But eventually I realised that documentation was frustrating, for various reasons, and that at least in this case there is a way to fix it in the code -- just block all access to a repo that is in ~/repositories, but which does not yet have the update hook setup correctly. Plus, the code does not impact anything else, and is basically just an extra check. [1]: http://gitolite.com/gitolite/basic-admin/index.html#appendix-1-bringing-existing-repos-into-gitolite --- src/gitolite-shell | 7 +++++++ src/lib/Gitolite/Common.pm | 20 ++++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/gitolite-shell b/src/gitolite-shell index 072e0ff..6c4c462 100755 --- a/src/gitolite-shell +++ b/src/gitolite-shell @@ -113,6 +113,13 @@ sub main { $ENV{GL_REPO} = $repo; my $aa = ( $verb =~ 'upload' ? 'R' : 'W' ); + # catch rare race when moving repos into gitolite control + _die "$aa any $repo $user DENIED by fallthru" . + "\n(or you mis-spelled the reponame)" + unless update_hook_present($repo); + # this error message is exactly the same as that from elsewhere in the + # code, for the usual reasons (avoid leaking information) + # set up env vars from options set for this repo env_options($repo); diff --git a/src/lib/Gitolite/Common.pm b/src/lib/Gitolite/Common.pm index 7a52f4b..3f47b37 100644 --- a/src/lib/Gitolite/Common.pm +++ b/src/lib/Gitolite/Common.pm @@ -19,6 +19,8 @@ package Gitolite::Common; ssh_fingerprint_file ssh_fingerprint_line + + update_hook_present ); #>>> use Exporter 'import'; @@ -235,14 +237,28 @@ sub cleanup_conf_line { chomp($repo); $repo =~ s/\.git$//; $repo =~ s(^\./)(); - push @phy_repos, $repo unless $repo =~ m(/$); - # tolerate bare repos within ~/repositories but silently ignore them + next if $repo =~ m(/$); + # tolerate non-bare repos within ~/repositories but silently ignore them + next unless update_hook_present($repo); + # ignore repos that don't yet have the update hook + push @phy_repos, $repo; } trace( 3, scalar(@phy_repos) . " physical repos found" ); return sort_u( \@phy_repos ); } } +sub update_hook_present { + my $repo = shift; + + return 1 unless -d "$ENV{GL_REPO_BASE}/$repo.git"; # non-existent repo is fine + + my $x = readlink("$ENV{GL_REPO_BASE}/$repo.git/hooks/update"); + return 1 if $x and $x eq "$ENV{GL_ADMIN_BASE}/hooks/common/update"; + + return 0; +} + # generate a timestamp sub gen_ts { my ( $s, $min, $h, $d, $m, $y ) = (localtime)[ 0 .. 5 ]; -- cgit v1.2.3-65-gdbad From 75993386fe33d2f85caea0ea41c8e86602a8f4ef Mon Sep 17 00:00:00 2001 From: Sitaram Chamarty Date: Sat, 8 Sep 2018 15:40:48 +0530 Subject: warn about unknown triggers David Bremner found that 'gitolite trigger foo', where foo is some arbitrary string, silently no-ops. The "gitolite trigger X" command only makes sense when X is POST_COMPILE or POST_CREATE, or, if it's a custom trigger type [1], when there is a section with that name in the rc file with a list of scripts to run. Anything else is an error, and should not silently no-op. [1]: for example, http://gitolite.com/gitolite/odds-and-ends/#using-pubkeys-obtained-from-elsewhere --- src/gitolite | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/gitolite b/src/gitolite index 4a4cbf5..c11e047 100755 --- a/src/gitolite +++ b/src/gitolite @@ -71,6 +71,11 @@ if ( $command eq 'setup' ) { compile(@args); } elsif ( $command eq 'trigger' ) { + my $s = $args[0]; + _die "trigger section '$s' not found in rc" + unless $s eq 'POST_COMPILE' + or $s eq 'POST_CREATE' + or ( exists $rc{$s} and ref( $rc{$s} ) eq 'ARRAY' ); trigger(@args); } elsif ( my $c = _which( "commands/$command", 'x' ) ) { -- cgit v1.2.3-65-gdbad From 144d8a202edaa30b19b0946051630da8ca561c6b Mon Sep 17 00:00:00 2001 From: Sitaram Chamarty Date: Sat, 8 Sep 2018 16:11:49 +0530 Subject: v3.6.9 --- CHANGELOG | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 345f2e2..9c3998a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,9 @@ +2018-08-07 v3.6.9 prevent racy access to repos in process of migration to + gitolite + + 'info' learns new '-p' option to show only physical repos + (as opposed to wild repos) + 2018-07-12 v3.6.8 fix bug when deleting *all* hooks for a repo allow trailing slashes in repo names -- cgit v1.2.3-65-gdbad