move triggers into their own subdir...
...otherwise 'gitolite help' was getting too confusing, mixing up stuff that users should not be running directly (even on the server) ---- implementation notes: those who are worried about the '../triggers/' in various parts of the code here, remember you can only do that from a command line on the server. Remote users can only use commands that have been explicitly listed in the COMMANDS hash in the rc file. This means they can't even access other commands in the same directory as, say, the 'info' command, so a '../' is definitely not going to work.
This commit is contained in:
parent
96ccbf0c1c
commit
07cf7fedfe
11 changed files with 6 additions and 6 deletions
133
src/triggers/post-compile/ssh-authkeys
Executable file
133
src/triggers/post-compile/ssh-authkeys
Executable file
|
@ -0,0 +1,133 @@
|
|||
#!/usr/bin/perl
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use File::Temp qw(tempfile);
|
||||
|
||||
use lib $ENV{GL_BINDIR};
|
||||
use Gitolite::Rc;
|
||||
use Gitolite::Common;
|
||||
|
||||
$|++;
|
||||
|
||||
# can be called directly, or as a post-update hook. Since it ignores
|
||||
# arguments anyway, it hardly matters.
|
||||
|
||||
my $ab = `gitolite query-rc -n GL_ADMIN_BASE`;
|
||||
trace( 2, "'keydir' not found in '$ab'; exiting" ), exit if not -d "$ab/keydir";
|
||||
my $akdir = "$ENV{HOME}/.ssh";
|
||||
my $akfile = "$ENV{HOME}/.ssh/authorized_keys";
|
||||
my $glshell = `gitolite query-rc -n GL_BINDIR` . "/gitolite-shell";
|
||||
my $auth_options = auth_options();
|
||||
|
||||
sanity();
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
_chdir($ab);
|
||||
|
||||
# old data
|
||||
my $old_ak = slurp($akfile);
|
||||
my @non_gl = grep { not /^# gito.*start/ .. /^# gito.*end/ } slurp($akfile);
|
||||
chomp(@non_gl);
|
||||
my %seen = map { $_ => 'a non-gitolite key' } ( fp(@non_gl) );
|
||||
# die 1;
|
||||
|
||||
# pubkey files
|
||||
chomp( my @pubkeys = `find keydir -type f -name "*.pub" | sort` );
|
||||
my @gl_keys = ();
|
||||
for my $f (@pubkeys) {
|
||||
my $fp = fp($f);
|
||||
if ( $seen{$fp} ) {
|
||||
_warn "$f duplicates $seen{$fp}, sshd will ignore it";
|
||||
} else {
|
||||
$seen{$fp} = $f;
|
||||
}
|
||||
push @gl_keys, grep { /./ } optionise($f);
|
||||
}
|
||||
|
||||
# dump it out
|
||||
if (@gl_keys) {
|
||||
my $out = join( "\n", map { my $_ = $_; chomp($_); $_ } @non_gl, "# gitolite start", @gl_keys, "# gitolite end" ) . "\n";
|
||||
|
||||
my $ak = slurp($akfile);
|
||||
_die "$akfile changed between start and end of this program!" if $ak ne $old_ak;
|
||||
_print( $akfile, $out );
|
||||
}
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
sub sanity {
|
||||
_die "$glshell not found; this should NOT happen..." if not -f $glshell;
|
||||
_die "$glshell found but not readable; this should NOT happen..." if not -r $glshell;
|
||||
_die "$glshell found but not executable; this should NOT happen..." if not -x $glshell;
|
||||
|
||||
_warn "$akdir missing; creating a new one" if not -d $akdir;
|
||||
_warn "$akfile missing; creating a new one" if not -f $akfile;
|
||||
|
||||
_mkdir($akdir, 0700) if not -d $akfile;
|
||||
if ( not -f $akfile ) {
|
||||
_print( $akfile, "" );
|
||||
chmod 0700, $akfile;
|
||||
}
|
||||
}
|
||||
|
||||
sub auth_options {
|
||||
my $auth_options = `gitolite query-rc AUTH_OPTIONS`;
|
||||
chomp($auth_options);
|
||||
$auth_options ||= "no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty";
|
||||
|
||||
return $auth_options;
|
||||
}
|
||||
|
||||
sub fp {
|
||||
# input: see below
|
||||
# output: a (list of) FPs
|
||||
my $in = shift || '';
|
||||
if ( $in =~ /\.pub$/ ) {
|
||||
# single pubkey file
|
||||
_die "bad pubkey file '$in'" unless $in =~ $REPONAME_PATT;
|
||||
return fp_file($in);
|
||||
} elsif ( -f $in ) {
|
||||
# an authkeys file
|
||||
return map { fp_line($_) } grep { !/^#/ and /\S/ } slurp($in);
|
||||
} else {
|
||||
# one or more actual keys
|
||||
return map { fp_line($_) } grep { !/^#/ and /\S/ } ( $in, @_ );
|
||||
}
|
||||
}
|
||||
|
||||
sub fp_file {
|
||||
my $f = shift;
|
||||
my $fp = `ssh-keygen -l -f '$f'`;
|
||||
chomp($fp);
|
||||
_die "fingerprinting failed for $f" unless $fp =~ /([0-9a-f][0-9a-f](:[0-9a-f][0-9a-f])+)/;
|
||||
$fp = $1;
|
||||
return $fp;
|
||||
}
|
||||
|
||||
sub fp_line {
|
||||
my ( $fh, $fn ) = tempfile();
|
||||
print $fh shift;
|
||||
close $fh;
|
||||
my $fp = fp_file($fn);
|
||||
unlink $fn;
|
||||
return $fp;
|
||||
}
|
||||
|
||||
sub optionise {
|
||||
my $f = shift;
|
||||
|
||||
my $user = $f;
|
||||
$user =~ s(.*/)(); # foo/bar/baz.pub -> baz.pub
|
||||
$user =~ s/(\@[^.]+)?\.pub$//; # baz.pub, baz@home.pub -> baz
|
||||
|
||||
my @line = slurp($f);
|
||||
if ( @line != 1 ) {
|
||||
_warn "$f does not contain exactly 1 line; ignoring";
|
||||
return '';
|
||||
}
|
||||
chomp(@line);
|
||||
return "command=\"$glshell $user\",$auth_options $line[0]";
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue