5

I'm trying to set up a secure git repository server using ssh-keys and git-shell. Since our user database is stored in a central LDAP directory, I can't change users' default shell to git-shell, so I've tried prepending the git-shell command to the public key in the authorized_users file like this:

command="git-shell -c $SSH_ORIGINAL_COMMAND" ssh-dss AAAAB3NzaC1kc3...

However, git-shell won't even allow me to clone the repository:

    dhcp202:git-ws frank$ git clone ssh://gitserver/var/repos/git/myrepo/
    Cloning into myrepo...
    fatal: What do you think I am? A shell?
    fatal: The remote end hung up unexpectedly

Any ideas appreciated...

Frank Brenner
  • 175
  • 5
  • 11

3 Answers3

2

I've made a solution using LDAP, OpenSSH (>4.9) and git-shell.

OpenSSH's ForceCommand is perfect for the job. Consider the following configuration (everyone except admins have to use git-shell):

Match group *,!admin    
    ForceCommand /usr/bin/git-shell -c "$SSH_ORIGINAL_COMMAND"

Access control is defined using ACL-s and reponame access groups.

setfacl -bR -m default:group:$REPONAME:rwX -m group:$REPONAME:rwX $GITROOT/$REPONAME
setfacl -R -m default:group:$REPONAME-ro:r-X -m group:$REPONAME-ro:r-X $GITROOT/$REPONAME

Don't forget to run "nscd -i group", after each change.

Andor

user77376
  • 193
  • 1
  • 5
1

You will find a similar mechanism with gitolite, based on ssh and forced command.
(including ldap queries).
It don't allow interactive shell however, which could be your issue there.

The OP Frank Brenner adds:

Ah, I figured it out - the command has to be in single quotes. I suppose $SSH_ORIGINAL_COMMAND was getting expanded before git-shell was started.

That is confirmed in the gitolite forced command script is a Perl one, ending with:

# ----------------------------------------------------------------------------
#       over to git now
# ----------------------------------------------------------------------------

if ($ENV{REQUEST_URI}) {
    log_it($ENV{REQUEST_URI});
    exec $ENV{GIT_HTTP_BACKEND};
    # the GIT_HTTP_BACKEND env var should be set either by the rc file, or as
    # a SetEnv in the apache config somewhere
}

log_it();

$repo = "'$REPO_BASE/$repo.git'";
exec("git", "shell", "-c", "$verb $repo") unless $verb eq 'git-init';

Note the $repo = "'$REPO_BASE/$repo.git'" line: it does contains single quotes.

VonC
  • 2,683
  • 5
  • 30
  • 49
  • Thanks for the info, but shouldn't git-shell as forced-command allow a "clone" operation? – Frank Brenner Mar 23 '11 at 14:15
  • @FRank: yes, but I suppose there is an issue in the way you are calling `git-shell` (btw, did you try "`git shell`" instead of "`git-shell`"?) – VonC Mar 23 '11 at 14:19
  • Yes I did try "git shell ...", to no avail, though. – Frank Brenner Mar 23 '11 at 15:17
  • Ah, I figured it out - the command has to be in single quotes. I suppose $SSH_ORIGINAL_COMMAND was getting expanded before git-shell was started... – Frank Brenner Mar 23 '11 at 15:58
  • @Frank: excellent. I have included your solution in my answer, pointing out the single quotes in the gitolite forced-command script as well. – VonC Mar 23 '11 at 16:11
0

This authorized_keys works for me and is properly shell quoted:

restrict,command="/usr/bin/git-shell -c \"$SSH_ORIGINAL_COMMAND\"" ssh-rsa AAAAB3NzaC1yc2EAA...

man sshd describes the authorized_keys file format:

A quote may be included in the command by quoting it with a backslash.

The same man page describes restrict:

Enable all restrictions, i.e. disable port, agent and X11 forwarding, as well as disabling PTY allocation and execution of ~/.ssh/rc. If any future restriction capabilities are added to authorized_keys files they will be included in this set.

jmou
  • 101