aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin H. Johnson <robbat2@gentoo.org>2017-06-29 14:12:26 -0700
committerRobin H. Johnson <robbat2@gentoo.org>2017-06-29 14:12:26 -0700
commit454205ea080840e607d8a792f995a7a9ecc49f2c (patch)
treea0cfe30867547b99e1c062e66b9df9d6d959e2f1
parentMerge tag 'v3.6.6' (diff)
parentadd example PRE_GIT code for blocking access (IP-check) (diff)
downloadgitolite-gentoo-master.zip
gitolite-gentoo-master.tar.gz
gitolite-gentoo-master.tar.bz2
Merge remote-tracking branch 'upstream/master'HEADgitolite-gentoo-3.6.6.1master
-rwxr-xr-xcontrib/triggers/IP-check43
-rwxr-xr-xcontrib/utils/testconf119
-rw-r--r--src/lib/Gitolite/Common.pm4
-rw-r--r--src/lib/Gitolite/Conf/Load.pm24
-rw-r--r--src/lib/Gitolite/Conf/Store.pm5
-rw-r--r--src/lib/Gitolite/Conf/Sugar.pm17
-rw-r--r--src/lib/Gitolite/Rc.pm4
-rwxr-xr-xsrc/triggers/post-compile/ssh-authkeys-split2
-rwxr-xr-xsrc/triggers/post-compile/update-git-configs8
-rwxr-xr-xsrc/triggers/repo-specific-hooks17
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