password access to gitolite using real users
This commit is contained in:
parent
63f18a5adf
commit
c69c10366d
46
contrib/real-users/gl-shell
Executable file
46
contrib/real-users/gl-shell
Executable 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
110
contrib/real-users/gl-shell-setup
Executable 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
|
145
contrib/real-users/password-access.mkd
Normal file
145
contrib/real-users/password-access.mkd
Normal 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
|
Loading…
Reference in a new issue