diff options
author | Robin H. Johnson <robbat2@gentoo.org> | 2017-06-29 14:12:26 -0700 |
---|---|---|
committer | Robin H. Johnson <robbat2@gentoo.org> | 2017-06-29 14:12:26 -0700 |
commit | 454205ea080840e607d8a792f995a7a9ecc49f2c (patch) | |
tree | a0cfe30867547b99e1c062e66b9df9d6d959e2f1 | |
parent | Merge tag 'v3.6.6' (diff) | |
parent | add example PRE_GIT code for blocking access (IP-check) (diff) | |
download | gitolite-gentoo-454205ea080840e607d8a792f995a7a9ecc49f2c.tar.gz gitolite-gentoo-454205ea080840e607d8a792f995a7a9ecc49f2c.tar.bz2 gitolite-gentoo-454205ea080840e607d8a792f995a7a9ecc49f2c.zip |
Merge remote-tracking branch 'upstream/master'gitolite-gentoo-3.6.6.1
-rwxr-xr-x | contrib/triggers/IP-check | 43 | ||||
-rwxr-xr-x | contrib/utils/testconf | 119 | ||||
-rw-r--r-- | src/lib/Gitolite/Common.pm | 4 | ||||
-rw-r--r-- | src/lib/Gitolite/Conf/Load.pm | 24 | ||||
-rw-r--r-- | src/lib/Gitolite/Conf/Store.pm | 5 | ||||
-rw-r--r-- | src/lib/Gitolite/Conf/Sugar.pm | 17 | ||||
-rw-r--r-- | src/lib/Gitolite/Rc.pm | 4 | ||||
-rwxr-xr-x | src/triggers/post-compile/ssh-authkeys-split | 2 | ||||
-rwxr-xr-x | src/triggers/post-compile/update-git-configs | 8 | ||||
-rwxr-xr-x | src/triggers/repo-specific-hooks | 17 |
10 files changed, 228 insertions, 15 deletions
diff --git a/contrib/triggers/IP-check b/contrib/triggers/IP-check new file mode 100755 index 0000000..9a4fda1 --- /dev/null +++ b/contrib/triggers/IP-check @@ -0,0 +1,43 @@ +#!/bin/bash + +# Check an IP before allowing access. + +# This is also a generic example of how to add arbitrary checks at the PRE_GIT +# stage, in order to control fetch/clone as well, not just push operations +# (VREFs, in contrast, only work for pushes). + +# Notice how repo-specific information is being passed to this code (bullet 3 +# below). For more on that, see: +# https://gitolite.com/gitolite/dev-notes/#appendix-1-repo-specific-environment-variables + +# Instructions: + +# 1. put this in an appropriate triggers directory (read about non-core +# code at http://gitolite.com/gitolite/non-core/ for more on this; the +# cookbook may also help here). + +# 2. add a line: +# PRE_GIT => [ 'IP-check' ], +# just before the "ENABLE" line in the rc file + +# 3. add a line like this to the "repo ..." section in gitolite.conf: +# option ENV.IP_allowed = 1.2.3.0/24 +# take care that this expression is valid, in the sense that passing it +# to 'ipcalc -n' will return the part before the "/". I.e., in this +# example, 'ipcalc -n 1.2.3.0/24' should (and does) return 1.2.3.0. + +# ---- + +[ -n "$GL_OPTION_IP_allowed" ] || exit 0 + +expected=${GL_OPTION_IP_allowed%/*} + mask=${GL_OPTION_IP_allowed#*/} + +current_ip=${SSH_CONNECTION%% *} + +eval `ipcalc -n $current_ip/$mask` + +[ "$expected" == "$NETWORK" ] && exit 0 + +echo >&2 "IP $current_ip does not match allowed block $GL_OPTION_IP_allowed" +exit 1 diff --git a/contrib/utils/testconf b/contrib/utils/testconf new file mode 100755 index 0000000..fda7e79 --- /dev/null +++ b/contrib/utils/testconf @@ -0,0 +1,119 @@ +#!/bin/bash + +# this is meant to be run on your *client* (where you edit and commit files +# in a gitolite-admin *working* repo), not on the gitolite server. +# +# TO USE +# ====== + +# To use this, first upgrade gitolite to the latest on the server; you need at +# least v3.6.7. +# +# Then, on the client: +# +# 1. copy this file (contrib/utils/testconf in the latest gitolite) to +# somewhere in your $PATH +# 2. modify the following lines if you wish (default should be fine for +# most people): + + # a semi-permanent area to play in (please delete it manually if you want to start afresh). + testconf=$HOME/GITOLITE-TESTCONF + # the gitolite source code + gitolite_url=git://github.com/sitaramc/gitolite + +# 3. go to your gitolite-admin clone and make suitable changes; see example +# below. No need to push to the server, yet. +# 4. run 'testconf` +# +# CAVEAT: include files are not handled the same way gitolite parsing handles +# them -- we just cat all the conf files together, in sorted order. +# +# If the tests ran OK, push your changes to the server as usual. + +# EXAMPLE changes to gitolite.conf +# ================================ +# Say you have these rules in the conf file: +# +# repo foo +# R = u1 +# RW = u2 +# RW+ = u3 +# +# To create test code for this, add the following lines to the conf file. +# +# =begin testconf +# # you can put arbitrary bash code here, but a simple example follows +# +# ok() { "$@" && echo ok || echo "not ok ($*)"; } +# nok() { ! "$@" && echo ok || echo "not ok ($*)"; } +# +# ok gitolite access -q foo u1 R +# nok gitolite access -q foo u1 W +# +# ok gitolite access -q foo u2 W +# nok gitolite access -q foo u2 + +# +# ok gitolite access -q foo u3 + +# =end +# +# Note that you can actually put in any bash code between the 'begin' and +# 'end' lines; the above is just a useful sample/template. +# +# Because of the 'begin' and 'end' lines, gitolite will ignore those lines +# when processing the conf file ON THE SERVER. +# +# (optional) TAP compliance +# ========================= +# if you add a line 'echo 1..5' (in this case, since there are 5 ok/nok lines; +# you will certainly have more) to the top the file, you can run +# +# prove `which testconf` +# +# which will give you a much nicer output. The only issue is if you have +# include files, you will need to put that in the file whose name is sorted +# first! + +# ---------------------------------------------------------------------- +od=$PWD + +# prep + +mkdir -p $testconf +cd $testconf + +export HOME=$PWD +export PATH=$PWD/gitolite/src:$PATH + +[ -d gitolite ] || { + + echo getting gitolite source... + git clone $gitolite_url gitolite + echo + + echo installing gitolite... + gitolite/install >/dev/null + echo + + echo setting up gitolite... + gitolite setup -a admin + echo + +} + +# copy conf from $od + +rm -rf $testconf/.gitolite/conf +mkdir -p $testconf/.gitolite/conf +cp -a $od/conf/* $testconf/.gitolite/conf/ + +# compile+ + +gitolite compile +gitolite trigger POST_COMPILE + +# snarf bits of code from conf files and run them + +cat `find $testconf/.gitolite/conf -type f -name "*.conf" | sort` | + perl -ne ' + print if /^=begin testconf$/ .. /^=end$/ and not /^=(begin|end)/; + ' | /bin/bash diff --git a/src/lib/Gitolite/Common.pm b/src/lib/Gitolite/Common.pm index 166a4df..7a52f4b 100644 --- a/src/lib/Gitolite/Common.pm +++ b/src/lib/Gitolite/Common.pm @@ -305,7 +305,7 @@ sub gl_log { require Sys::Syslog; Sys::Syslog->import(qw(:standard)); - openlog("gitolite" . ( $ENV{GL_TID} ? "[$ENV{GL_TID}]" : "" ), "pid", "local0"); + openlog("gitolite" . ( $ENV{GL_TID} ? "[$ENV{GL_TID}]" : "" ), "pid", $Gitolite::Rc::rc{LOG_FACILITY} || 'local0'); $syslog_opened = 1; } @@ -355,7 +355,7 @@ sub ssh_fingerprint_file { # Return a valid fingerprint or undef my $fp = undef; if($output =~ /((?:MD5:)?(?:[0-9a-f]{2}:){15}[0-9a-f]{2})/i or - $output =~ m{((?:RIPEMD|SHA)\d+:[A-ZA-z0-9+/=]+)}i) { + $output =~ m{((?:RIPEMD|SHA)\d+:[A-Za-z0-9+/=]+)}i) { $fp = $1; } return wantarray ? ($fp, $output) : $fp; diff --git a/src/lib/Gitolite/Conf/Load.pm b/src/lib/Gitolite/Conf/Load.pm index 15b1d03..a439fc8 100644 --- a/src/lib/Gitolite/Conf/Load.pm +++ b/src/lib/Gitolite/Conf/Load.pm @@ -348,7 +348,7 @@ sub load_1 { return if not $split_conf{$repo}; my $cc = "./gl-conf"; - _die "parse '$cc' failed: " . ( $! or $@ ) unless do $cc; + _die "parse '$cc' failed: " . ( $@ or $! ) unless do $cc; $last_repo = $repo; $repos{$repo} = $one_repo{$repo}; @@ -583,15 +583,24 @@ sub list_groups { =for list_users Usage: gitolite list-users [<repo name pattern>] -List all users and groups explicitly named in a rule. User names not -mentioned in an access rule will not show up; you have to run 'list-members' -on each group name yourself to see them. +List all users and groups explicitly named in a rule. + +- you will have to run 'list-members' on each group name to expand it -- for + details and caveats on that please see its help message. +- User names not mentioned in an access rule will not show up at all (for + example, if you have users who only have access via an '@all' rule). WARNING: may be slow if you have thousands of repos. The optional repo name pattern is an unanchored regex; it can speed things up if you're interested only in users of a matching set of repos. This is only an optimisation, not an actual access list; you will still have to pipe it to 'gitolite access' with appropriate arguments to get an actual access list. + +NOTE: If you're running in ssh mode, it may be simpler to parse the authorized +keys file in ~/.ssh, like so: + perl -lne '/ ([a-z0-9]+)"/; print $1 if $1' < ~/.ssh/authorized_keys | sort -u +If you're running in http mode, only your web server knows all the potential +user names. =cut sub list_users { @@ -677,6 +686,13 @@ Usage: gitolite list-members <group name> - list all members of a group - takes one group name + +'@all' is not expandable in this context. Also, if you have GROUPLIST_PGM set +in your rc file[1], gitolite cannot expand group names completely; only your +external database can. + +[1]: http://gitolite.com/gitolite/conf.html#ldap + =cut sub list_members { diff --git a/src/lib/Gitolite/Conf/Store.pm b/src/lib/Gitolite/Conf/Store.pm index 5568b3f..c7f9ab5 100644 --- a/src/lib/Gitolite/Conf/Store.pm +++ b/src/lib/Gitolite/Conf/Store.pm @@ -288,8 +288,6 @@ sub store_1 { my ( %one_repo, %one_config ); - open( my $compiled_fh, ">", "$repo.git/gl-conf" ) or return; - my $dumped_data = ''; if ( $repos{$repo} ) { $one_repo{$repo} = $repos{$repo}; @@ -303,8 +301,7 @@ sub store_1 { $dumped_data .= Data::Dumper->Dump( [ \%one_config ], [qw(*one_config)] ); } - print $compiled_fh $dumped_data; - close $compiled_fh; + _print( "$repo.git/gl-conf", $dumped_data ); $split_conf{$repo} = 1; } diff --git a/src/lib/Gitolite/Conf/Sugar.pm b/src/lib/Gitolite/Conf/Sugar.pm index 986494b..68ad728 100644 --- a/src/lib/Gitolite/Conf/Sugar.pm +++ b/src/lib/Gitolite/Conf/Sugar.pm @@ -68,6 +68,7 @@ sub sugar { $lines = owner_desc($lines); $lines = name_vref($lines); $lines = role_names($lines); + $lines = skip_block($lines); return $lines; } @@ -179,5 +180,21 @@ sub role_names { return \@ret; } +sub skip_block { + my $lines = shift; + + my @out = (); + for (@$lines) { + my $skip = 0; + $skip = 1 if /^= *begin testconf$/; + # add code for other types of blocks here as needed + + next if $skip .. /^= *end$/; + push @out, $_; + } + + return \@out; +} + 1; diff --git a/src/lib/Gitolite/Rc.pm b/src/lib/Gitolite/Rc.pm index 2ee96e8..5a0e83d 100644 --- a/src/lib/Gitolite/Rc.pm +++ b/src/lib/Gitolite/Rc.pm @@ -527,6 +527,8 @@ __DATA__ # LOG_DEST => 'repo-log,normal', # LOG_DEST => 'repo-log,syslog', # LOG_DEST => 'repo-log,syslog,normal', + # syslog 'facility': defaults to 'local0', uncomment if needed. For example: + # LOG_FACILITY => 'local4', # roles. add more roles (like MANAGER, TESTER, ...) here. # WARNING: if you make changes to this hash, you MUST run 'gitolite @@ -607,7 +609,7 @@ __DATA__ # essential (unless you're using smart-http mode) 'ssh-authkeys', - # creates git-config enties from gitolite.conf file entries like 'config foo.bar = baz' + # creates git-config entries from gitolite.conf file entries like 'config foo.bar = baz' 'git-config', # creates git-daemon-export-ok files; if you don't use git-daemon, comment this out diff --git a/src/triggers/post-compile/ssh-authkeys-split b/src/triggers/post-compile/ssh-authkeys-split index cd9a603..b838fb1 100755 --- a/src/triggers/post-compile/ssh-authkeys-split +++ b/src/triggers/post-compile/ssh-authkeys-split @@ -65,7 +65,7 @@ do f=$SKD/$base@$seq.pub echo "$line" > $f # similar sanity check as main ssh-authkeys script - if ! ssh-keygen -l -f $f + if ! ssh-keygen -l -f $f >/dev/null then echo 1>&2 "ssh-authkeys-split: bad line $seq in keydir/$k" rm -f $f diff --git a/src/triggers/post-compile/update-git-configs b/src/triggers/post-compile/update-git-configs index a58a85d..bdb83ac 100755 --- a/src/triggers/post-compile/update-git-configs +++ b/src/triggers/post-compile/update-git-configs @@ -48,6 +48,7 @@ sub fixup_config { my $gc = git_config( $pr, '.', 1 ); while ( my ( $key, $value ) = each( %{$gc} ) ) { next if $key =~ /^gitolite-options\./; + $value =~ s/(@\w+)/expand_group($1)/ge if $rc{EXPAND_GROUPS_IN_CONFIG}; if ( $value ne "" ) { system( "git", "config", "--file", "$RB/$pr.git/config", $key, $value ); } else { @@ -55,3 +56,10 @@ sub fixup_config { } } } + +sub expand_group { + my $g = shift; + my @m = @{ Gitolite::Conf::Load::list_members($1) }; + return join(" ", @m) if @m; + return $g; +} diff --git a/src/triggers/repo-specific-hooks b/src/triggers/repo-specific-hooks index 7ed28e5..bba7a58 100755 --- a/src/triggers/repo-specific-hooks +++ b/src/triggers/repo-specific-hooks @@ -13,9 +13,15 @@ _die "repo-specific-hooks: '$rc{LOCAL_CODE}/hooks/repo-specific' does not exist _chdir( $ENV{GL_REPO_BASE} ); -@ARGV = ("gitolite list-phy-repos | gitolite git-config -ev -r % gitolite-options\\.hook\\. |"); +if ($ARGV[0] eq 'POST_CREATE') { + # just the repo given in arg-2 + @ARGV = ("gitolite git-config -ev -r $ARGV[1] gitolite-options\\.hook\\. |"); +} else { + # POST_COMPILE, all repos + @ARGV = ("gitolite list-phy-repos | gitolite git-config -ev -r % gitolite-options\\.hook\\. |"); +} -my $driver = "$rc{LOCAL_CODE}/hooks/multi-hook-driver"; +my $driver = $rc{MULTI_HOOK_DRIVER} || "$rc{LOCAL_CODE}/hooks/multi-hook-driver"; # Hook Driver { local $/ = undef; @@ -67,7 +73,12 @@ for my $repo (keys %repo_hooks) { } my $src = $rc{LOCAL_CODE} . "/hooks/repo-specific/$code"; + + # if $code has slashes in it, flatten it for use in $dst, to avoid + # having to re-create those intermediate sub-directories + $code =~ s(/)(_)g; my $dst = "$repo.git/hooks/$hook.$counter-$code"; + unless ( -x $src ) { _warn "repo-specific-hooks: '$src' doesn't exist or is not executable"; next; @@ -85,7 +96,7 @@ for my $repo (keys %repo_hooks) { } __DATA__ -#/bin/sh +#!/bin/sh # Determine what input the hook needs # post-update takes args, pre/post-receive take stdin |