Restrict SSH access to use only mercurial

Imagine we’ve got mercurial repository at shared hosting, with only one ssh account. We can run mercurial as a cgi, but I describe another version of its usage here - ssh access.

It’s okay to use mercurial via ssh when only you pushes changes to repository, but developing something by oneself may be boring, so let’s imagine we have to provide access to our repo for some other developers. The problem is that we don’t want to give full ssh access to them.

The key to solution is options in authorized_keys. This file allows one to limit commands run via ssh by per-key base.

command=“command” Specifies that the command is executed whenever this key is used for authentication. The command supplied by the user (if any) is ignored.

Below is a python wrapper script to use as an only command that is allowed to run via ssh for some unprivileged developer (it allows him to work only with mercurial repositories).

#!/usr/bin/env python
import os
import re
r = re.compile('^hg -R (S%2B) serve --stdio$')
match = re.search(r, os.environ['SSH_ORIGINAL_COMMAND'])
if match:
    repo_path = match.groups()[0]
    if os.path.exists(repo_path):
        os.execvp('hg', ['hg', '-R', repo_path, 'serve', '--stdio'])

Save this code as hg-wrapper and add to ~/.ssh/authorized_keys the following line:

command="path/to/hg-wrapper",no-pty ssh-rsa SSH-KEY-HERE....

Now the one with the ssh key from this line can only use ssh for mercurial repositories access.


P.S.: If you’re using Ubuntu (Debian maybe have this too), look at file /usr/share/doc/mercurial/examples/hg-ssh from mercurial package. It’s the same approach as above, but somewhat more official. :)