Using git-shell and restricting developers to commit to their own projects
git
Solution
I use something a bit simpler, all you need is to setup three files, the `authorized_keys` file, the `gitsecurity.rb` file and a permissions file `gitpermissions`. For simplicity they can all go in the git accounts .ssh folder. (Basic unix admin skills required to understand herein)
The `gitpermissions` file looks like this, and should be fairly self explanitory:
repo1.git|jane|rw
repo1.git|james|r
repo2.git|bob|rw
The `autorized_keys` file looks something like this:
command="/Users/git/.ssh/gitsecurity.rb jacob",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa rFaivBw.....5Rws jacob
command="/Users/git/.ssh/gitsecurity.rb bob",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa rFaivBw.....5Rws bob
Finally the `gitsecurity.rb` script, just copy and paste it:
#!/usr/bin/ruby
class GitPermission
attr_accessor :username;
attr_accessor :repository;
attr_accessor :read;
attr_accessor :write;
def initialize(line)
bits = line.split('|');
if(bits.length!=3)
$stderr.puts "Invalid configuration file"
Process.exit(4)
end
@repository = bits[0]
@username = bits[1]
@read = bits[2].include?("r")
@write = bits[2].include?("w")
end
end
if(!ENV.has_key?("SSH_ORIGINAL_COMMAND"))
$stderr.puts "SSH not allowed to the git account."
Process.exit(1);
end
command = ENV["SSH_ORIGINAL_COMMAND"];
if(!ARGV.length == 1)
$stderr.puts "Authorised keys file misconfigured, username not specified correctly."
Process.exit(1);
end
if(!ARGV[0].match(/^[A-Za-z0-9]+$/))
$stderr.puts "Authorised keys file misconfigured, username contains invalid characters: "+ARGV[0];
Process.exit(1);
end
username = ARGV[0]
if(!command.match(/^git[ -]upload-pack /) && !command.match(/^git[ -]receive-pack /))
$stderr.puts "Only git commands are allowed."
Process.exit(2);
end
repository = command[(command.index(' ')+1)..-1]
if(!repository.match(/'.*'/))
$stderr.puts "Repository parameter incorrect."
Process.exit(2);
end
repository = repository[1,repository.length-2]
begin
file = File.new("/Users/git/.ssh/gitpermissions", "r")
while (line = file.gets)
p = GitPermission.new(line);
if(p.repository == repository && p.username == username)
if((p.write == true || (p.read == true && command.match(/^git[ -]upload-pack/))) )
exec "/usr/local/git/bin/" + command
Process.exit(0);
end
end
end
file.close
rescue => err
$stderr.puts "Problem with server configuration: #{err}"
Process.exit(4)
end
$stderr.puts "You do not have permission to complete this operation"
Process.exit(5)
Problem
We are using `git-shell` to ensure that the git account is only used for git operations. This works great. However before we move to using git full time, how do we set it up similar to github whereby depending on your public key you may only commit to your own repositories? As far as I can tell the github people may be rolling their own `git-shell`, the source code appears to be very simple to hack