new server-side program "gl-tool", subcommand "shell-add"

Previous implementations of "give shell access to some gitolite users"
feature were crap.  There was no easy/elegant way to ensure that someone
who had repo admin access would not manage to get himself shell access.

Giving someone shell access requires that you should have shell access
in the first place, so the simplest way is to enable it from the server
side only.

So now that we decided to do that, we may as well prepare for other,
future, commands by starting a server-side utility program with
sub-commands (the only current one being "shell-add")
This commit is contained in:
Sitaram Chamarty 2010-04-09 20:52:32 +05:30
parent 5deffee3cf
commit 246165537d
4 changed files with 90 additions and 42 deletions

View file

@ -75,19 +75,6 @@ $GIT_PATH="";
# --------------------------------------
# if you want to give shell access to any gitolite user(s), name them here.
# Please see doc/6-ssh-troubleshooting.mkd for details on how this works.
# Do not add people to this list indiscriminately. AUDITABILITY OF ACCESS
# CONTROL CHANGES (AND OF REPO ACCESSES) WILL BE COMPROMISED IF ADMINS CAN
# FIDDLE WITH THE ACTUAL (PLAIN TEXT) LOG FILES THAT GITOLITE KEEPS, WHICH
# THEY CAN EASILY DO IF THEY HAVE A SHELL.
# syntax: space separated list of gitolite usernames in *one* string variable.
# $SHELL_USERS = "alice bob";
# --------------------------------------
# ----------------------------------------------------------------------

View file

@ -386,32 +386,23 @@ instance if you have *two* gitolite servers you are administering)?
We've managed (thanks to an idea from Jesse Keating) to make it possible for a
single key to allow both gitolite access *and* shell access.
This is done by:
This is done by copying the pubkey (to which you want to give shell access) to
the server and running either
* (**on the server**) listing all such users in a variable called
`$SHELL_USERS` in the `~/.gitolite.rc` file. For example:
cd $HOME/.gitolite # assuming default $GL_ADMINDIR in ~/.gitolite.rc
src/gl-tool shell-add ~/foo.pub
$SHELL_USERS = "alice bob";
or
(Note the syntax: a space separated list of users in one string variable).
gl-tool shell-add ~/foo.pub
* (**on your client**) make at least a dummy change to your clone of the
gitolite-admin repo and push it.
The first method is to be used if you used the **user-install** mode, while
the second method is for the **system-install followed by user-setup** mode
(see doc/0-INSTALL.mkd, section on "install methods", for more on this)
**IMPORTANT UPGRADE NOTE**: a previous implementation of this feature worked
by adding people to a special group (`@SHELL`) in the *config* file. This
meant that anyone with gitolite-admin repo write access could add himself to
the `@SHELL` group and push, thus obtaining shell.
This is not a problem for most setups, but if someone wants to separate these
two privileges (the right to push the admin repo and the right to get a shell)
then it does pose a problem. Since the "rc" file can only be edited by
someone who already has shell access, we now use that instead, even though
this forces a change in the syntax.
To migrate from the old scheme to the new one, add a new variable
`$SHELL_USERS` to `~/.gitolite.rc` on the server with the appropriate names in
it. **It is best to do this directly on the server *before* upgrading to this
version.** (After the upgrade is done and tested you can remove the `@SHELL`
lines from the gitolite config file).
**IMPORTANT UPGRADE NOTE**: previous implementations of this feature were
crap. There was no easy/elegant way to ensure that someone who had repo admin
access would not manage to get himself shell access.
Giving someone shell access requires that you should have shell access in the
first place, so the simplest way is to enable it from the server side only.

View file

@ -52,7 +52,7 @@ $Data::Dumper::Sortkeys = 1;
open STDOUT, ">", "/dev/null" if (@ARGV and shift eq '-q');
# these are set by the "rc" file
our ($GL_ADMINDIR, $GL_CONF, $GL_KEYDIR, $GL_CONF_COMPILED, $REPO_BASE, $REPO_UMASK, $PROJECTS_LIST, $GIT_PATH, $SHELL_USERS, $GL_WILDREPOS, $GL_GITCONFIG_KEYS, $GL_PACKAGE_HOOKS);
our ($GL_ADMINDIR, $GL_CONF, $GL_KEYDIR, $GL_CONF_COMPILED, $REPO_BASE, $REPO_UMASK, $PROJECTS_LIST, $GIT_PATH, $GL_WILDREPOS, $GL_GITCONFIG_KEYS, $GL_PACKAGE_HOOKS);
# and these are set by gitolite.pm
our ($REPONAME_PATT, $REPOPATT_PATT, $USERNAME_PATT, $AUTH_COMMAND, $AUTH_OPTIONS, $ABRT, $WARN);
@ -537,11 +537,7 @@ for my $pubkey (glob("*"))
print STDERR "WARNING: a pubkey file can only have one line (key); ignoring $pubkey\n";
next;
}
if ($SHELL_USERS and $SHELL_USERS =~ /(^|\s)$user(\s|$)/) {
print $newkeys_fh "command=\"$AUTH_COMMAND -s $user\",$AUTH_OPTIONS ";
} else {
print $newkeys_fh "command=\"$AUTH_COMMAND $user\",$AUTH_OPTIONS,no-pty ";
}
print $newkeys_fh "command=\"$AUTH_COMMAND $user\",$AUTH_OPTIONS,no-pty ";
print $newkeys_fh $pubkey_content;
}
# lint check 3; a little more severe than the first two I guess...

74
src/gl-tool Executable file
View file

@ -0,0 +1,74 @@
#!/bin/sh
# BEGIN USAGE
# $0 -- make some server side tasks easier
# Usage:
# $0 [sub-command [args]]
# Security notes: this program does not do any sanitisation of input. You're
# running it at the CLI on the server, so you already have the power to do
# whatever you want anyway.
# current sub-commands:
# (1) REPLACE THE OLD $SHELL_USERS MECHANISM
# $0 shell-add foo.pub
# adds the pubkey in foo.pub into the authkeys file with "-s" argument (shell
# access) and user "foo". The line will be added *before* the "# gitolite
# start" section, so that a gitolite-admin push will not affect it.
# Although there is no "shell-remove" sub-command, you can do that quite
# easily by editing ~/.ssh/authorized_keys and deleting the appropriate line.
# END USAGE
die() { echo "$@"; exit 1; }
if [ -z "$1" ]
then
perl -ne 's/\$0/$ARGV/ge; print if /BEGIN USAGE/../END USAGE/' $0 | grep -v USAGE | cut -c3-
exit 1
fi
if [ "$1" = "shell-add" ]
then
# sanity checks
[ -z "$2" ] && exec $0
[ -f "$2" ] || die "$2 does not exist"
wc -l < $2 | grep '^1$' >/dev/null || die "$2 contains more than one line"
# must be kept consistent with what's in src/gl-compile-conf; on the plus
# side, it's not likely to change anytime soon!
AUTH_OPTIONS="no-port-forwarding,no-X11-forwarding,no-agent-forwarding"
bindir=`echo $0 | perl -lpe 's/^/$ENV{PWD}\// unless /^\//; s/\/[^\/]+$//;'`
pubkey_file=$2
user=`basename $pubkey_file .pub`
authline="command=\"$bindir/gl-auth-command -s $user\",$AUTH_OPTIONS `cat $pubkey_file`";
authkeys=$HOME/.ssh/authorized_keys
for i in 1
do
perl -lne "last if /# gitolite start/; print unless /gl-auth-command -s $user/; " $authkeys
echo $authline
perl -lne "print if /# gitolite start/ .. 0; " $authkeys
done > $authkeys.new
diff -u $authkeys $authkeys.new && die no change to authkey file
echo
echo If the above diff looks ok, press enter. Else press Ctrl-C.
read dummy
cat $authkeys > $authkeys.old
cat $authkeys.new > $authkeys
exit 0
fi
die "could not understand command $1"