Skip to content

Instantly share code, notes, and snippets.

@pogoapp
Created November 15, 2012 17:45
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pogoapp/4080041 to your computer and use it in GitHub Desktop.
Save pogoapp/4080041 to your computer and use it in GitHub Desktop.
#!/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
#!/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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment