public
Created

  • Download Gist
authorized_keys.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
#!/usr/bin/ruby
 
LOGGING = true
LOGFILE = File.join(File.dirname(__FILE__), 'authorized_script_log')
 
# if we're logging, set up log file in advance
if LOGGING
begin
LOG = File.open(LOGFILE, 'a')
at_exit { LOG.close }
rescue SystemCallError
LOG = nil
end
end
 
def log(msg)
LOG.puts "[#{Time.now}] #{msg}" if LOGGING
end
 
key = STDIN.gets.strip
user = ARGV.first
log("trying to authorize key: #{key} | #{user} | #{ARGV.inspect}")
 
unless user == 'git'
log "[ERROR] invalid user!"
Kernel.exit(1)
end
 
unless key =~ /^ssh-(?:dss|rsa) [A-Za-z0-9+\/](=+)?+/
log "[ERROR] invalid key!"
Kernel.exit(1)
end
 
require 'redis'
uri = URI.parse(ENV['REDISDB_URL'])
uri.port ||= 6379
redis = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password, :db => 4)
 
user_val = redis.get(key)
user_id, name = user_val.split(':') if user_val
 
if user_id and name
STDOUT.print %Q[command="bundle exec /app/pogo-git #{user_id} #{name}",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty]
Kernel.exit(0)
else
log "lookup failed: #{key} | #{user_val} | #{user_id} | #{name}"
Kernel.exit(1)
end
pogo-git.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
#!/usr/bin/ruby
 
require 'redis'
 
class GitAction
attr_reader :user_id, :repo, :cmd
def initialize(user_id, ssh_command)
@user_id = user_id
# input e.g. "git-upload-pack '/test.git'" or "git-upload-pack 'test.git'"
@cmd, repo_str = ssh_command.split(' ', 2)
repo_fname = File.basename(repo_str).tr("'", '')
unless cmd.match(/^git[ -]upload-pack$/) || cmd.match(/^git[ -]receive-pack$/)
$stderr.puts "Only git commands are allowed, not: #{cmd}"
Process.exit(2)
end
# FIXME: junky regex
unless repo_fname.match(/\w+\.git/)
$stderr.puts "Repository parameter incorrect: #{repo_fname}"
Process.exit(2)
end
@repo = File.basename(repo_fname, '.git')
ensure_setup if valid_user?
true
end
def valid_user?
repo_user_ids.include?(user_id)
end
# TODO: read-only users?
def allowed?
valid_user?
end
def repo_user_ids
@repo_user_ids ||= redis.smembers(repo) || []
end
def ensure_setup
`GIT_TEMPLATE_DIR=/app/repo-template git init --bare #{path} &> /dev/null` unless Dir.exists?(path)
`ln -nfs /app/hooks #{path}/hooks`
end
def repo_dir
'/app/share/gitolite/repositories'
end
def path
"#{repo_dir}/#{repo}.git"
end
def redis
@redis ||= begin
uri = URI.parse(ENV['REDISDB_URL'])
uri.port ||= 6379
redis = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password, :db => 4)
end
end
end
 
###
 
unless ssh_command = ENV["SSH_ORIGINAL_COMMAND"]
$stderr.puts "SSH not allowed to the git account."
Process.exit(1)
end
 
user_id, name = *ARGV
 
begin
git_action = GitAction.new(user_id, ssh_command)
if git_action.allowed?
ENV['GL_REPO'] = git_action.repo
ENV['GL_USER'] = name
exec "/usr/bin/#{git_action.cmd} #{git_action.path}"
Process.exit(0)
else
$stderr.puts "#{name} does not have permission to #{git_action.cmd}"
Process.exit(5)
end
rescue => e
$stderr.puts "Error!"
Process.exit(4)
end

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.