aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.Developer8
-rw-r--r--README.Gentoo42
-rwxr-xr-xdist.sh31
-rwxr-xr-xsrc/commands/sshkeys-lint4
-rwxr-xr-xsrc/gitolite-shell2
-rw-r--r--src/lib/Gitolite/Conf/Load.pm40
-rw-r--r--src/lib/Gitolite/Rc.pm16
-rw-r--r--src/lib/Gitolite/Setup.pm3
-rwxr-xr-xsrc/triggers/post-compile/ssh-authkeys79
-rwxr-xr-xsrc/triggers/post-compile/ssh-authkeys-split4
10 files changed, 224 insertions, 5 deletions
diff --git a/README.Developer b/README.Developer
new file mode 100644
index 0000000..913fe8a
--- /dev/null
+++ b/README.Developer
@@ -0,0 +1,8 @@
+git remote set-url --push origin git+ssh://git@git.overlays.gentoo.org/proj/gitolite-gentoo.git
+git remote add upstream-g2 git://github.com/sitaramc/gitolite.git --no-tags -t g2
+git remote add upstream-g3 git://github.com/sitaramc/gitolite.git --no-tags -t master
+git fetch upstream-g2
+git fetch upstream-g3
+git branch -t -l upstream-g2 upstream-g2/g2
+git branch -t -l upstream-g3 upstream-g3/master
+git branch -t -l master-g2 origin/master-g2
diff --git a/README.Gentoo b/README.Gentoo
new file mode 100644
index 0000000..50d9c4b
--- /dev/null
+++ b/README.Gentoo
@@ -0,0 +1,42 @@
+gitolite-gentoo:
+
+Features:
+ SSH-Keys behavior
+ Also allow comments
+ Add the ability to preserve key options like from="1.1.1.1" (AUTH_OPTIONS_PRESERVE)
+ Some kind of key validation
+
+ Additional metadata can be provided to be passed to the gitolite environment
+ This can be useful if you want to pass additional metadata to the hooks,
+ for e.g. cia.vc or other services.
+ You can set a list of allow/parsed variables (GL_METADATA) and a list of
+ *required* variables (GL_METADATA_REQUIRED).
+
+ Example:
+ .gitolite.rc:
+ %RC = (
+ ...
+ GL_METADATA => [ 'realname-ascii', 'cia-user' ],
+ GL_METADATA_REQUIRED => [ 'realname-ascii', 'cia-user' ],
+ ...
+ )
+
+ keydir/$user.pub:
+ # realname-ascii: foo bar
+ # cia-user: foo
+ ssh-rsa ... user@host
+
+ The hooks can then use $realname_ascii and $cia_user from the
+ environment.
+ Each '-' (dash) will be replaced by an '_' (underscore).
+
+ If you want other metadata or information from the .pub files, you
+ should look at the base Gitolite v3 documentation for "distinguishing
+ one key from another" and enable the '--key-file-name' option to
+ 'ssh-authkeys'.
+
+Non-Features:
+ SSH-Keys
+ In Gitolite-Gentoo v2 we supported multiple keys in a single file. This
+ support is discontinued. You should migrate to one key per user; we are
+ using $EMAIL@$N for Gentoo in future.
diff --git a/dist.sh b/dist.sh
new file mode 100755
index 0000000..1e24254
--- /dev/null
+++ b/dist.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+branch=$(git rev-parse --abbrev-ref HEAD)
+
+if [ "${branch}" = "master-g2" ]; then
+ # GL2
+ export GL_BINDIR="$(pwd)/src"
+ export GL_RC="$(pwd)/conf/example.gitolite.rc"
+
+ dirs="conf/ hooks/ src/"
+else
+ # GL3
+ export GL_LIBDIR="$(pwd)/src"
+
+ dirs="src/"
+ perl_opts="-Isrc/lib/"
+fi
+
+if [ -z "${1}" ]; then
+ tag=$(git tag | grep '^gitolite-gentoo-.*$' | sort -r | head -n 1)
+else
+ tag=$1
+fi
+
+for foo in $(find ${dirs} -type f); do
+ [ "${foo:$((${#foo}-3))}" = ".pm" ] && { perl $perl_opts -c $foo; continue; }
+ [ -n "$(grep -m 1 '^#!/usr/bin/perl' $foo)" ] && { perl $perl_opts -c $foo; continue; }
+done
+
+git archive --prefix=${tag}/ --format tar $branch > ${tag}.tar
+bzip2 -9 ${tag}.tar
diff --git a/src/commands/sshkeys-lint b/src/commands/sshkeys-lint
index 3f07b13..b67e77d 100755
--- a/src/commands/sshkeys-lint
+++ b/src/commands/sshkeys-lint
@@ -120,7 +120,9 @@ sub check {
sub user {
my $user = '';
- $user ||= "user $1" if /^command=.*gitolite-shell (.*?)"/;
+ # Remove all other options
+ s/^(((no-)?((agent|port|x11)-forwarding|pty|cert-authority|user-rc|(environment|from|permitopen|principals|tunnel)="[^"]+")),)+//g;
+ $user ||= "user $1" if /^command="[^"]*gitolite-shell (.*?)"/;
$user ||= "unknown command" if /^command/;
$user ||= "shell access" if /$KEYTYPE_REGEX/;
diff --git a/src/gitolite-shell b/src/gitolite-shell
index 072e0ff..e8efe3d 100755
--- a/src/gitolite-shell
+++ b/src/gitolite-shell
@@ -114,7 +114,7 @@ sub main {
my $aa = ( $verb =~ 'upload' ? 'R' : 'W' );
# set up env vars from options set for this repo
- env_options($repo);
+ env_options($repo, $user);
# auto-create?
if ( repo_missing($repo) and access( $repo, $user, '^C', 'any' ) !~ /DENIED/ ) {
diff --git a/src/lib/Gitolite/Conf/Load.pm b/src/lib/Gitolite/Conf/Load.pm
index 7dea259..57d1396 100644
--- a/src/lib/Gitolite/Conf/Load.pm
+++ b/src/lib/Gitolite/Conf/Load.pm
@@ -234,7 +234,47 @@ sub env_options {
$ENV{ "GL_OPTION_" . $1 } = $v;
}
+ # The user find block might return, so we should switch directory now.
+ # GL_ADMIN_BASE should also be absolute
chdir($cwd);
+
+ my $user = shift;
+ if($user) {
+ my @pubkeys;
+ # ssh-authkeys --key-file-name passes the actual pubkey file!
+ if(defined($ARGV[0])) {
+ my $f = $rc{GL_ADMIN_BASE}.'/'.$ARGV[0];
+ push @pubkeys, $f if -f $f;
+ }
+ # This catches the base 'user.pub', 'user@host.pub', exact matches
+ push @pubkeys, `find $rc{GL_ADMIN_BASE}/keydir -type f -name "${user}.pub"`;
+ # this catches 'user@host@NN.pub' variant, for email-named users with multiple keys
+ push @pubkeys, `find $rc{GL_ADMIN_BASE}/keydir -type f -name "${user}@*.pub"` if $user =~ m/@/;
+ chomp(@pubkeys);
+ return if $#pubkeys <= 0;
+
+ # If they have multiple pubkeys, they SHOULD be the same, but we check
+ # anyway.
+ foreach my $pubkey (@pubkeys) {
+ my $pk_fh = _open('<', $pubkey);
+ while(defined(my $line = <$pk_fh>)) {
+ chomp($line);
+ next if $line !~ m/^\s*#/;
+ $line =~ s/^\s*#\s*//;
+
+ my ($variable, $value) = split(/:\s*/, $line, 2);
+
+ if(grep(/^\Q${variable}\E$/, @{$rc{'GL_METADATA'}})) {
+ if(length($value) > 0) {
+ $variable =~ s/-/_/g;
+ _die "Metadata $variable has conflicted values: '$ENV{$variable}' vs '$value'" if(defined($ENV{$variable}) and $ENV{$variable} ne $value);
+ $ENV{$variable} = $value;
+ }
+ }
+ }
+ close($pk_fh);
+ }
+ }
}
sub option {
diff --git a/src/lib/Gitolite/Rc.pm b/src/lib/Gitolite/Rc.pm
index 41996fb..5a0e83d 100644
--- a/src/lib/Gitolite/Rc.pm
+++ b/src/lib/Gitolite/Rc.pm
@@ -308,7 +308,12 @@ sub trigger {
# name, so setup env from options
require Gitolite::Conf::Load;
Gitolite::Conf::Load->import('env_options');
- env_options( $_[0] ) if $_[0];
+ if($_[0] && $_[1]) {
+ env_options($_[0], $_[1]);
+ }
+ elsif($_[0]) {
+ env_options($_[0]);
+ }
if ( exists $rc{$rc_section} ) {
if ( ref( $rc{$rc_section} ) ne 'ARRAY' ) {
@@ -536,6 +541,15 @@ __DATA__
# enable caching (currently only Redis). PLEASE RTFM BEFORE USING!!!
# CACHE => 'Redis',
+ # Define which metadata variables shall be exported to the gitolite
+ # environment.
+ # Those variables can be used in hooks, e.g. for cia.vc
+ # A pubkey file might contain one or more of those variable.
+ # They can be defined by e.g:"# git-username: idl0r"
+ # Each '-' (dash) will be replaced by an '_' (underscore).
+ #GL_METADATA => [ "git-username", "git-email", "git-realname", "git-realname-ascii", "cia-vc-username" ],
+ #GL_METADATA_REQUIRED => [ "git-username", "git-email", "git-realname" ],
+
# ------------------------------------------------------------------
# rc variables used by various features
diff --git a/src/lib/Gitolite/Setup.pm b/src/lib/Gitolite/Setup.pm
index 8ad5d34..69a9be0 100644
--- a/src/lib/Gitolite/Setup.pm
+++ b/src/lib/Gitolite/Setup.pm
@@ -92,7 +92,8 @@ sub args {
if ($pubkey) {
$pubkey =~ /\.pub$/ or _die "'$pubkey' name does not end in .pub";
tsh_try("cat $pubkey") or _die "'$pubkey' not a readable file";
- tsh_lines() == 1 or _die "'$pubkey' must have exactly one line";
+ my @lines = grep {!/^(#|$)/} tsh_lines();
+ scalar(@lines) == 1 or _die "'$pubkey' must have exactly one non-empty, non-comment line";
tsh_try("ssh-keygen -l -f $pubkey") or _die "'$pubkey' does not seem to be a valid ssh pubkey file";
$admin = $pubkey;
diff --git a/src/triggers/post-compile/ssh-authkeys b/src/triggers/post-compile/ssh-authkeys
index cd59aec..a95018d 100755
--- a/src/triggers/post-compile/ssh-authkeys
+++ b/src/triggers/post-compile/ssh-authkeys
@@ -8,6 +8,11 @@ use lib $ENV{GL_LIBDIR};
use Gitolite::Rc;
use Gitolite::Common;
+# To parse the pubkeyfile with options etc.
+# 0.16 adds ecdsa keys
+# 0.17 adds ed25519 keys
+use Net::SSH::AuthorizedKeysFile 0.17;
+
$|++;
# best called via 'gitolite trigger POST_COMPILE'; other modes at your own
@@ -32,6 +37,7 @@ my $akdir = "$ENV{HOME}/.ssh";
my $akfile = "$ENV{HOME}/.ssh/authorized_keys";
my $glshell = $rc{GL_BINDIR} . "/gitolite-shell";
my $auth_options = auth_options();
+my $auth_options_preserve = auth_options_preserve();
sanity();
@@ -55,7 +61,7 @@ for my $f (@pubkeys) {
} else {
$seen{$fp} = $f;
}
- push @gl_keys, grep { /./ } optionise($f);
+ @gl_keys = (@gl_keys, optionise_gentoo($f));
}
# dump it out
@@ -92,6 +98,13 @@ sub auth_options {
return $auth_options;
}
+sub auth_options_preserve {
+ my $auth_options_preserve = $rc{AUTH_OPTIONS_PRESERVE};
+ $auth_options_preserve ||= "from";
+
+ return $auth_options_preserve;
+}
+
sub fp {
# input: see below
# output: a (list of) FPs
@@ -124,6 +137,7 @@ sub fp_line {
return $fp;
}
+# NOTE: optionise() is not used in gitolite-gentoo
sub optionise {
my $f = shift;
@@ -140,3 +154,66 @@ sub optionise {
return "command=\"$glshell $user" . ( $kfn ? " $f" : "" ) . "\",$auth_options $line[0]";
}
+sub optionise_gentoo {
+ my $f = shift;
+
+ my $user = $f;
+ $user =~ s(.*/)(); # foo/bar/baz.pub -> baz.pub
+ $user =~ s/(\@[^.]+)?\.pub$//; # baz.pub, baz@home.pub -> baz
+
+ # Metadata check
+ if(exists($rc{"GL_METADATA_REQUIRED"}) && @{$rc{"GL_METADATA_REQUIRED"}} gt 0) {
+ my @not_met = @{$rc{"GL_METADATA_REQUIRED"}};
+ my $pubkey = _open('<', $f);
+ while(defined(my $line = <$pubkey>)) {
+ chomp($line);
+ next if $line !~ m/^\s*#\s*[-a-zA-Z0-9_]+:/;
+ $line =~ s/^\s*#\s*//;
+
+ my ($variable, $value) = split(/:\s*/, $line, 2);
+
+ if(grep(/^\Q${variable}\E$/, @{$rc{"GL_METADATA_REQUIRED"}})) {
+ if(length($value) > 0) {
+ @not_met = grep(!/^\Q${variable}\E$/, @not_met);
+ }
+ }
+ }
+ close($pubkey);
+
+ if( $#not_met ne -1 ) {
+ _warn "Skipping '${f}' due to missed required variables: ".join(", ", sort @not_met);
+ return ();
+ }
+ }
+
+ # Use strict mode to abort on faulty files
+ my $akf = Net::SSH::AuthorizedKeysFile->new( strict => 1, );
+ $akf->read($f);
+
+ my @keys = ();
+
+ foreach my $keyobj ($akf->keys()) {
+ if(!defined($keyobj)) {
+ _warn "Malformed key '${f}', skipping...\n";
+ next;
+ }
+
+ # Preserve only options specified in AUTH_OPTIONS_PRESERVE
+ foreach my $option (keys(%{$keyobj->options})) {
+ if(!grep(/^\Q${option}\E$/, split(",", $auth_options_preserve))) {
+ delete($keyobj->options->{$option});
+ }
+ }
+
+ # Add our options as well
+ foreach my $option (split(",", $auth_options)) {
+ $keyobj->option($option, 1);
+ }
+
+ $keyobj->option("command", "${glshell} ${user}" . ( $kfn ? " $f" : "" ));
+
+ push(@keys, $keyobj->as_string());
+ }
+
+ return @keys;
+}
diff --git a/src/triggers/post-compile/ssh-authkeys-split b/src/triggers/post-compile/ssh-authkeys-split
index 031bd07..a7d5133 100755
--- a/src/triggers/post-compile/ssh-authkeys-split
+++ b/src/triggers/post-compile/ssh-authkeys-split
@@ -29,6 +29,10 @@
# to enable, uncomment the 'ssh-authkeys-split' line in the ENABLE list in the
# rc file.
+echo "ERROR: ssh-authkeys-split is not support by gitolite-gentoo" 1>&2
+echo "ERROR: because metadata might be lost. You should split the keys manually!" 1>&2
+exit 1
+
cd $GL_ADMIN_BASE/keydir
rm -rf __split_keys__