I had a problem at work, where we needed to restrict vcs user’s access to only allow git and mercurial commands. There was a server that had been designated as the central repository server that everyone wash pushing to and pulling from, but as we added more users it became apparent that we should lock things down a bit to prevent repo tampering since everyone had shell access to the server and write permissions to their repos.
There are several existing solutions for this for git and mercurial individually but nothing that encompassed both of them. I found a great idea here Code Your Own Multi-User Private Git Server in 5 Minutes and extended it to include hg commands, then locked down the hg commands using the same logic as hg-ssh. I removed the read/write logic since hg handles commands differently than git, and I can control that with file permissions for the users and repos to a certain degree.
You need to setup command restricted authorized_keys files for each user, then point the command to this script.
# Example authorized_keys
# command="/usr/local/bin/vcs-srv jconway",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAA...examplekey...zzz email@example.com
# user is passed from authorized_keys
user = ARGV
command = ENV['SSH_ORIGINAL_COMMAND']
abort "No login, just git and hg commands" unless user and command
# check the supplied command contains a valid git action
valid_actions = ['git-receive-pack', 'git-upload-pack', 'hg']
action = command.split
abort "git and hg commands only" unless valid_actions.include? action
# user made a valid request so handing over to git-shell unless it's a mercurial request
Kernel.exec 'git', 'shell', '-c', command if action != 'hg'
# Make sure the hg command is safe
abort "quit trying to do fancy hg stuff" unless command.split == 'hg' and command.split == '-R' and command.split == 'serve' and command.split == '--stdio'
# If we made it this far, execute the command as is for mercurial
Here is an example of the authorized_keys file
command="/usr/local/bin/vcs-srv jconway",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAA...examplekey...zzz firstname.lastname@example.org
I then used puppet to manage authorized_keys files for each user.