password access to gitolite using real users

This commit is contained in:
Sitaram Chamarty 2011-09-13 15:11:51 +05:30
parent 63f18a5adf
commit c69c10366d
3 changed files with 301 additions and 0 deletions

46
contrib/real-users/gl-shell Executable file
View file

@ -0,0 +1,46 @@
#!/usr/bin/perl
use strict;
use warnings;
# ------------------------------------------------------------------------------
# site-local changes
# the original login shell your users had. Set this to something like
# "/sbin/nologin" or "/bin/false" if you don't want them to have a normal
# shell (i.e., you created these accounts *only* to provide a password
# authentication passthru to gitolite)
my $shell = "/bin/bash";
# the gitolite hosting user you want to forward git commands to. Typically
# this will be 'git' or perhaps 'gitolite', but actually could be anything
my $hosting_user = "gitolite-test";
# ------------------------------------------------------------------------------
# process normal logins (the ones that *don't* get forwarded to the gitolite
# hosting user)
# this is a normal login, not to be forwarded to the gitolite hosting user, if:
# - there are no arguments
exec($shell) unless @ARGV;
# - the first argument is not "-c"
exec($shell, @ARGV) unless $ARGV[0] eq '-c';
# - the second argument does not fit what git usually sends
exec($shell, @ARGV) unless $ARGV[1] =~ /^(git-receive-pack|git-upload-pack|git-upload-archive) '(\S+)'$/;
# - there *is* a local directory with the same name as the second part of argument #2
exec($shell, @ARGV) if -d $2;
# ------------------------------------------------------------------------------
# if all that failed, it means we have to forward this to the hosting user
# this message is important in debugging and trouble shooting; see documentation
print STDERR "[forwarding to $hosting_user\@localhost]\n";
# but first we check for rsa key
-f ".ssh/id_rsa" or die "ask your admin to add you to gitolite";
shift; # that pesky '-c'...
exec("ssh", "$hosting_user\@localhost", @ARGV);

110
contrib/real-users/gl-shell-setup Executable file
View file

@ -0,0 +1,110 @@
#!/bin/bash
# WARNING 1: probably contains bashisms galore. If you don't have bash,
# please install it.
# NOTE 1: this script is initially run as root, then it calls itself with an
# "su" so it can run as the hosting user.
# NOTE 2: if you'd rather do this manually, just do the first part as root,
# and the second part as the hosting user, with only the name of the user
# (alice) and her pub key (~alice/.ssh/id_rsa.pub) needing to be passed from
# root to the hosting user id.
# ------------------------------------------------------------------------------
# site-local changes
# the gitolite hosting user you want to forward git commands to. Typically
# this will be 'git' or perhaps 'gitolite', but actually could be anything
hosting_user="gitolite-test"
# absolute path of the gitolite-admin repo
admin_repo="/home/gitolite-test/repositories/gitolite-admin.git"
# the full path to the new login shell to replace these users' existing shell
new_shell="/usr/local/bin/gl-shell"
my_chsh() {
# please replace with appropriate command for your OS/distro. This one is
# suitable at least for Fedora, maybe others also
chsh -s $new_shell $1
}
# remove these 2 lines after you have done your customisation
[ -f /tmp/done.gl-shell-setup ] || { echo please customise $0 before using; exit 1; }
# ------------------------------------------------------------------------------
die() { echo "FATAL: $@" >&2; exit 1; }
# ------------------------------------------------------------------------------
euid=$(perl -e 'print $>')
if [ "$euid" = "0" ]
then
# --------------------------------------------------------------------------
# stuff to be done as root
# --------------------------------------------------------------------------
[ -n "$1" ] || die "need a valid username"
user=$1
id $user >/dev/null || die "need a valid username"
# now fix up the user's login shell
my_chsh $user
# drat... 'cd ~$user` doesn't work...
cd $(bash -c "echo ~$user") || die "can't cd to $user's home directory"
# now set up her rsa key, creating it if needed
[ -d .ssh ] || {
mkdir .ssh
chown $user .ssh
chmod go-w .ssh
}
[ -f .ssh/id_rsa.pub ] || {
ssh-keygen -q -N "" -f .ssh/id_rsa
chown $user .ssh/id_rsa .ssh/id_rsa.pub
chmod go-rw .ssh/id_rsa
chmod go-w .ssh/id_rsa.pub
}
# now run yourself as the hosting user, piping in the pubkey to STDIN, and
# passing the username whose key it is as argument 1.
cat .ssh/id_rsa.pub | su -l -c "$0 $user" $hosting_user
# finally, as $user (alice) ssh to the hosting_user once so that the
# hostkey checking gets done and you get the correct hostkey in
# ~user/.ssh/known_hosts
su -c "ssh -o StrictHostKeyChecking=no $hosting_user@localhost info" - $user
exit 0
else
# --------------------------------------------------------------------------
# stuff to be done as the hosting user
# --------------------------------------------------------------------------
user=$1
# make a temp dir and switch to it
export tmp=$(mktemp -d)
cd $tmp || die "could not cd to temp dir $tmp"
trap "rm -rf $tmp" 0
# clone the admin repo here
git clone $admin_repo .
# copy alice's pubkey, which was sent in via STDIN. We don't want to
# overwrite any *other* keys she may have, hence the @localhost part.
# (See "one user, many keys" in doc/3 for more on this @ part).
cat > keydir/$user@localhost.pub
# add commit push...
git add keydir/$user@localhost.pub
git diff --cached --quiet 2>/dev/null || git commit -am "$0: added/updated local key for $user"
gl-admin-push
# see doc for what/why this is
fi

View file

@ -0,0 +1,145 @@
# password access to gitolite
## (a.k.a: turning real users into gitolite users)
<a name="_problems"></a>
### problems
*Problem 1*: Here's one type of problem some admins have:
* Some of your users already have a real (unix) userid on the *same server*
as the gitolite hosting user.
* They don't all use ssh keys; some may still be using passwords and don't
want to change.
* They want to use this existing userid to access the gitolite served repos.
This document has a solution to this problem!
*Problem 2*: And here's a somewhat different one:
* Some of your users are not willing to use ssh keys; they're only
comfortable with passwords.
* But gitolite *requires* ssh key-based access; it can't work if you use a
password to get access (because then there is no way to distinguish one
user from another).
Well, as the math folks say, "reduce it to a known problem". Give them all
Unix userids on the same server as gitolite, with password access, so that
problem 2 reduces to problem 1 ;-)
<font color="gray">If you created these Unix accounts *only* to solve this
pesky password problem, and do not wish them to actually have shell access or
be able to do anything else on the server, don't worry -- that's easy to
handle too.</font>
<a name="_solution"></a>
### solution
Briefly, the Unix userid is made to act like a "gitolite proxy".
Here's a more detailed explanation.
Normal gitolite flow, for a user called Alice, is like this:
ssh key
alice ----------------------------------------> git
(workstation) (REQUIRED) (server)
However, if Alice has her own real (unix) userid on the server, and the admin
sets things up according to this document, then Alice can do this:
password
alice ------ OR -----> alice
(workstation) ssh key (server)
The **important** thing to note here is that she doesn't need ssh keys; she
can use passwords if she wants to.
Behind the scenes, the gitolite/git conversation is being transparently
forwarded to the gitolite hosting user, so it is *actually* like this:
password ssh key
alice ------ OR -----> alice - - - - - - - > git
(workstation) ssh key (server) (REQUIRED) (localhost)
The second connection is transparent to Alice; she still thinks she is talking
to her own userid. In git URL terms, she simply uses `alice@server:reponame`,
without realising that behind the scenes this is getting forwarded to
`git@server:reponame`.
This second connection *does* require ssh keys, but since they're all on the
server, it's scriptable and automatable so the user doesn't have to deal with
these pesky ssh keys.
<a name="_some_hints_notes_and_caveats"></a>
### some hints, notes and caveats
* This doesn't mean all your users have to be like this. You can have
normal users also. In fact, you can have users who give you a pub key
from their workstation the normal way, as well as use this method.
* Special commands and ADCs will NOT work from the workstation for such
users; they have to log on to their own userid on the server and run the
appropriate command (such as `ssh git@localhost info`) from there. <font
color="gray">We could have handled the known special commands (info,
expand, setperms, etc.), but considering that an ADC could be called
*anything*, a general solution is impossible.</font>
* If you server's host key changes, you may have to manually fix up all the
host keys in all the user's `~/.ssh/known_hosts` files. Not too difficult
if you're sure they all have just the one host key, but if they have
multiple, you have to carefully delete and replace just the one line that
pertains to localhost. Scripts to do this cleanly are welcome...
<a name="_what_the_2_scripts_actually_do"></a>
### what the 2 scripts actually do
* `gl-shell` will become the new login shell for these users. This shell
will forward git clone/fetch/push requests to the gitolite server.
This redirection is so transparent that I had to explicitly code a message
("forwarding to git@server") to make troubleshooting easier.
* `gl-shell-setup` is run by root, once for each user. (You can run it
multiple times; it's designed to be idempotent). As root, it changes the
user's shell to `gl-shell` (full path), then sets up an RSA key for the
user if one is not already present. Then it runs as `git` (or whatever
the hosting user is) and takes the pubkey and adds it as (to continue our
example) `alice@localhost.pub` in keydir of the admin repo, which is then
pushed.
Notice the use of [this trick][oumk] to allow Alice to allow users to have
other (gitolite normal) keys as well, such as perhaps from a laptop.
<a name="_setting_it_up"></a>
### setting it up
Here's how to set this up. First, the **one-time** tasks:
* Install gitolite as normal, if not already installed. This will require
you to use ssh keys for your (admin's) own access, but I assume that's ok.
* As root, copy the program `contrib/real-users/gl-shell` to
`/usr/local/bin`.
* As root, customise the program `/usr/local/bin/gl-shell`. You will need
to change only 2 variables at the top in a section clearly marked as
'site-local changes'.
* As root, copy `contrib/real-users/gl-shell-setup` to some place on root's
`$PATH` and customise it similarly to gl-shell. Note that there are many
more configurable values in this script. **NOTE** also that this includes
fixing the `chsh` command, which may be OS/distro dependent. The supplied
command is good for Fedora.
Now, for each user 'alice' that has her own real (unix) userid, and also needs
to access gitolite *via* her own id, run the command `gl-shell-setup alice`.
And that's really all there is to it.
[oumk]: http://sitaramc.github.com/gitolite/doc/3-faq-tips-etc.html#_one_user_many_keys