Commit 612a909e authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'git-refactoring' into 'master'

Git Refactoring
parents 189f88de 41e98174
web: bundle exec unicorn_rails -p $PORT -E development web: bundle exec unicorn_rails -p $PORT -E development -c config/unicorn_development.rb
worker: bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,common,default,gitlab_shell worker: bundle exec sidekiq -q post_receive,mailer,system_hook,project_web_hook,common,default,gitlab_shell
worker_processes 2
timeout 30
module API module API
# Internal access API # Internal access API
class Internal < Grape::API class Internal < Grape::API
DOWNLOAD_COMMANDS = %w{ git-upload-pack git-upload-archive }
PUSH_COMMANDS = %w{ git-receive-pack }
namespace 'internal' do namespace 'internal' do
# # Check if git command is allowed to project
# Check if ssh key has access to project code
# #
# Params: # Params:
# key_id - SSH Key id # key_id - ssh key id for Git over SSH
# user_id - user id for Git over HTTP
# project - project path with namespace # project - project path with namespace
# action - git action (git-upload-pack or git-receive-pack) # action - git action (git-upload-pack or git-receive-pack)
# ref - branch name # ref - branch name
...@@ -22,43 +18,25 @@ module API ...@@ -22,43 +18,25 @@ module API
# the wiki repository as well. # the wiki repository as well.
project_path = params[:project] project_path = params[:project]
project_path.gsub!(/\.wiki/,'') if project_path =~ /\.wiki/ project_path.gsub!(/\.wiki/,'') if project_path =~ /\.wiki/
key = Key.find(params[:key_id])
project = Project.find_with_namespace(project_path) project = Project.find_with_namespace(project_path)
git_cmd = params[:action]
return false unless project return false unless project
actor = if params[:key_id]
if key.is_a? DeployKey Key.find(params[:key_id])
key.projects.include?(project) && DOWNLOAD_COMMANDS.include?(git_cmd) elsif params[:user_id]
else User.find(params[:user_id])
user = key.user end
return false if user.blocked? return false unless actor
if Gitlab.config.ldap.enabled Gitlab::GitAccess.new.allowed?(
if user.ldap_user? actor,
# Check if LDAP user exists and match LDAP user_filter params[:action],
unless Gitlab::LDAP::Access.new.allowed?(user) project,
return false params[:ref],
end params[:oldrev],
end params[:newrev]
end )
action = case git_cmd
when *DOWNLOAD_COMMANDS
then :download_code
when *PUSH_COMMANDS
then
if project.protected_branch?(params[:ref])
:push_code_to_protected_branches
else
:push_code
end
end
user.can?(action, project)
end
end end
# #
......
...@@ -5,7 +5,7 @@ module Grack ...@@ -5,7 +5,7 @@ module Grack
class Auth < Rack::Auth::Basic class Auth < Rack::Auth::Basic
include Helpers include Helpers
attr_accessor :user, :project, :ref, :env attr_accessor :user, :project, :env
def call(env) def call(env)
@env = env @env = env
...@@ -80,24 +80,11 @@ module Grack ...@@ -80,24 +80,11 @@ module Grack
def authorize_request(service) def authorize_request(service)
case service case service
when 'git-upload-pack' when 'git-upload-pack'
can?(user, :download_code, project) # Serve only upload request.
when'git-receive-pack' # Authorization on push will be serverd by update hook in repository
refs.each do |ref| Gitlab::GitAccess.new.download_allowed?(user, project)
action = if project.protected_branch?(ref)
:push_code_to_protected_branches
else
:push_code
end
return false unless can?(user, action, project)
end
# Never let git-receive-pack trough unauthenticated; it's
# harmless but git < 1.8 doesn't like it
return false if user.nil?
true
else else
false true
end end
end end
...@@ -114,29 +101,5 @@ module Grack ...@@ -114,29 +101,5 @@ module Grack
def project def project
@project ||= project_by_path(@request.path_info) @project ||= project_by_path(@request.path_info)
end end
def refs
@refs ||= parse_refs
end
def parse_refs
input = if @env["HTTP_CONTENT_ENCODING"] =~ /gzip/
Zlib::GzipReader.new(@request.body).read
else
@request.body.read
end
# Need to reset seek point
@request.body.rewind
# Parse refs
refs = input.force_encoding('ascii-8bit').scan(/refs\/heads\/([\/\w\.-]+)/n).flatten.compact
# Cleanup grabare from refs
# if push to multiple branches
refs.map do |ref|
ref.gsub(/00.*/, "")
end
end
end end
end end
module Gitlab
class GitAccess
DOWNLOAD_COMMANDS = %w{ git-upload-pack git-upload-archive }
PUSH_COMMANDS = %w{ git-receive-pack }
attr_reader :params, :project, :git_cmd, :user
def allowed?(actor, cmd, project, ref = nil, oldrev = nil, newrev = nil)
case cmd
when *DOWNLOAD_COMMANDS
if actor.is_a? User
download_allowed?(actor, project)
elsif actor.is_a? DeployKey
actor.projects.include?(project)
elsif actor.is_a? Key
download_allowed?(actor.user, project)
else
raise 'Wrong actor'
end
when *PUSH_COMMANDS
if actor.is_a? User
push_allowed?(actor, project, ref, oldrev, newrev)
elsif actor.is_a? DeployKey
# Deploy key not allowed to push
return false
elsif actor.is_a? Key
push_allowed?(actor.user, project, ref, oldrev, newrev)
else
raise 'Wrong actor'
end
else
false
end
end
def download_allowed?(user, project)
if user_allowed?(user)
user.can?(:download_code, project)
else
false
end
end
def push_allowed?(user, project, ref, oldrev, newrev)
if user_allowed?(user)
action = if project.protected_branch?(ref)
:push_code_to_protected_branches
else
:push_code
end
user.can?(action, project)
else
false
end
end
private
def user_allowed?(user)
return false if user.blocked?
if Gitlab.config.ldap.enabled
if user.ldap_user?
# Check if LDAP user exists and match LDAP user_filter
unless Gitlab::LDAP::Access.new.allowed?(user)
return false
end
end
end
true
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment