Setting up a shared remote git repository without root privileges (solved) using ssh keys to manage per user access

bashgitrepositoryssh-keys

I'll first explain my setup. I'm working on a non-self managed system on which I have an account without root/elevated privileges. On this system I want to share multiple git repositories to different groups of people. The actions taken to realise a shared git repository follow below. I've divided them in commands executed in a bash terminal on the REMOTE and LOCAL system. ps: replace any variables surrounded by delimiters < and > with appropriate values.

———– REMOTE (my system): ———–

bash-4.2> mkdir -p <path>/<to>/project.git
bash-4.2> cd <path>/<to>/project.git
bash-4.2> git init --bare
bash-4.2> ssh-keygen -t rsa -f ~/.ssh/gitkey_rsa -N <password>
bash-4.2> echo "command=\"git-shell -c \\\"\$SSH_ORIGINAL_COMMAND\\\"\",
    no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty \
    $(cat ~/.ssh/gitkey_rsa.pub)" >> ~/.ssh/authorized_keys

These command do the following:

  1. create a git repository
  2. generate a ssh key
  3. add the key to authorized_keys with prepended restrictions

———– LOCAL (other users) ———–

bash-4.2> mv <path>/<to>/gitkey_rsa ~/.ssh
bash-4.2> echo -e "Host gitserver\n\
    \tHostName <remote server>\n\
    \tUser <remote user>\n\
    \tIdentityFile ~/.ssh/gitkey_rsa" >> ~/.ssh/config
bash-4.2> git clone gitserver:/home/<remote user>/<path>/<to>/project.git

These commands do the following:

  1. place rsa key in directory ~/.ssh
  2. add a rule to ~/.ssh/config specifying hostname 'gitserver' with key
  3. retrieve repository contents

The commands used are based on restrict access to only git. By using the restricted key, a user is only allowed to execute git commands. The problem is that the user is also allowed to access every git repository on the remote system. I'd like to restrict access to only one repository per ssh key. In other words, I'd like to restrict access to one folder, containing the git repository, through ssh key restrictions.

The solutions I have found thus far are: access only certain directories through ssh and Restrict SSH user to one folder. They either want you to install a (S)FTP server, WebDAV or create a new user with restricted privileges. This is not what I'm looking for, as it requires root privileges. Due to the fact that commands can be restricted with ssh key restrictions, isn't there a way to restrict access privileges as well?

Regards

Best Answer

Possible solution:

As I was typing the question I came up with a solution. But it seems to me there must be a simpler and more secure solution to this problem. What I did was change the value of 'command' in the authorized_keys file to:

command="~/somescript.sh" 

And 'somescript.sh' contains:

#!/bin/bash
ALLOW=(
    '/home/<user>/repository1.git'
    '/home/<user>/repository2.git'
)

case $SSH_ORIGINAL_COMMAND in
    "git-receive-pack"*|"git-upload-pack"*|"git-upload-archive"*)
        GITPATH=$(echo $SSH_ORIGINAL_COMMAND | sed -r "s:.*'([^']*)'.*:\1:g")
        ALLOWED="false"
        for ((i=0; i < ${#ALLOW[@]}; i++)); do
            if [ "${ALLOW[$i]}" == "$GITPATH" ]; then
                ALLOWED="true"; break;
            fi
        done

        if [ "$ALLOWED" == "true" ]; then
            eval "git-shell -c \"$SSH_ORIGINAL_COMMAND\""
        else
            echo "[ERROR] ACCESS DENIED" >&2
            exit 1
        fi
        ;;
    *)
        echo "[ERROR] Only git commands are allowed!" >&2
        exit 1
        ;;
esac

In the script I'm taking advantage of the fact that the commands git clone, git push and git pull produce on the REMOTE side:

git-upload-pack '<path>/<to>/<repository>', or
git-receive-pack '<path>/<to>/<repository>'

I specify repositories in variable ALLOW that are allowed to be accessed through the ssh key that uses the script, and simply compare them to the path specified in the issued git command (variable GITPATH). There is a security risk though, when multiple git commands are issued in one line. If the command contains at least one mention of an allowed repository, it executes the entire command. Any suggestions on improvement?

Related Question