Using git-shell and restricting developers to commit to their own projects
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 c开发者_如何学Code appears to be very simple to hack
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)
An option could be to use gitosis. (nice write-up here)
This script allows authenticated users can run arbitrary code under as the git user.
Example exploit: https://gist.github.com/ranmrdrakono/4959641
Suggested fix: https://gist.github.com/ranmrdrakono/4959672
Note that exec is given two parameters. The first one is the command to be executed (constant) and the second one ist the argument (which will not be interpreted by the shell).
精彩评论