Commit 3597ed8d authored by Rubén Dávila's avatar Rubén Dávila Committed by Rémy Coutable

Merge branch 'fix-unathorized-cloning-ee' into 'security'

Ensure external users are not able to clone disabled repositories.

EE MR for gitlab/gitlabhq!2017

See merge request !506
Signed-off-by: default avatarRémy Coutable <remy@rymai.me>
parent 88b03a4c
...@@ -21,10 +21,6 @@ class Projects::GitHttpClientController < Projects::ApplicationController ...@@ -21,10 +21,6 @@ class Projects::GitHttpClientController < Projects::ApplicationController
def authenticate_user def authenticate_user
@authentication_result = Gitlab::Auth::Result.new @authentication_result = Gitlab::Auth::Result.new
if project && project.public? && download_request?
return # Allow access
end
if allow_basic_auth? && basic_auth_provided? if allow_basic_auth? && basic_auth_provided?
login, password = user_name_and_password(request) login, password = user_name_and_password(request)
...@@ -41,6 +37,10 @@ class Projects::GitHttpClientController < Projects::ApplicationController ...@@ -41,6 +37,10 @@ class Projects::GitHttpClientController < Projects::ApplicationController
send_final_spnego_response send_final_spnego_response
return # Allow access return # Allow access
end end
elsif project && download_request? && Guest.can?(:download_code, project)
@authentication_result = Gitlab::Auth::Result.new(nil, project, :none, [:download_code])
return # Allow access
end end
send_challenges send_challenges
......
...@@ -82,11 +82,7 @@ class Projects::GitHttpController < Projects::GitHttpClientController ...@@ -82,11 +82,7 @@ class Projects::GitHttpController < Projects::GitHttpClientController
def upload_pack_allowed? def upload_pack_allowed?
return false unless Gitlab.config.gitlab_shell.upload_pack return false unless Gitlab.config.gitlab_shell.upload_pack
if user access_check.allowed? || ci?
access_check.allowed?
else
ci? || project.public?
end
end end
def access def access
......
...@@ -31,7 +31,7 @@ module LfsHelper ...@@ -31,7 +31,7 @@ module LfsHelper
def lfs_download_access? def lfs_download_access?
return false unless project.lfs_enabled? return false unless project.lfs_enabled?
project.public? || ci? || lfs_deploy_token? || user_can_download_code? || build_can_download_code? ci? || lfs_deploy_token? || user_can_download_code? || build_can_download_code?
end end
def user_can_download_code? def user_can_download_code?
......
class Guest
class << self
def can?(action, subject)
Ability.allowed?(nil, action, subject)
end
end
end
...@@ -76,7 +76,7 @@ module Auth ...@@ -76,7 +76,7 @@ module Auth
case requested_action case requested_action
when 'pull' when 'pull'
requested_project.public? || build_can_pull?(requested_project) || user_can_pull?(requested_project) build_can_pull?(requested_project) || user_can_pull?(requested_project)
when 'push' when 'push'
build_can_push?(requested_project) || user_can_push?(requested_project) build_can_push?(requested_project) || user_can_push?(requested_project)
else else
......
...@@ -3,10 +3,19 @@ ...@@ -3,10 +3,19 @@
module Gitlab module Gitlab
class GitAccess class GitAccess
include PathLocksHelper include PathLocksHelper
UnauthorizedError = Class.new(StandardError)
DOWNLOAD_COMMANDS = %w{ git-upload-pack git-upload-archive } DOWNLOAD_COMMANDS = %w{ git-upload-pack git-upload-archive }
PUSH_COMMANDS = %w{ git-receive-pack } PUSH_COMMANDS = %w{ git-receive-pack }
GIT_ANNEX_COMMANDS = %w{ git-annex-shell } GIT_ANNEX_COMMANDS = %w{ git-annex-shell }
ALL_COMMANDS = DOWNLOAD_COMMANDS + PUSH_COMMANDS + GIT_ANNEX_COMMANDS
ERROR_MESSAGES = {
upload: 'You are not allowed to upload code for this project.',
download: 'You are not allowed to download code from this project.',
deploy_key: 'Deploy keys are not allowed to push code.',
no_repo: 'A repository for this project does not exist yet.'
}
attr_reader :actor, :project, :protocol, :user_access, :authentication_abilities attr_reader :actor, :project, :protocol, :user_access, :authentication_abilities
...@@ -19,23 +28,12 @@ module Gitlab ...@@ -19,23 +28,12 @@ module Gitlab
end end
def check(cmd, changes) def check(cmd, changes)
return build_status_object(false, "Git access over #{protocol.upcase} is not allowed") unless protocol_allowed? check_protocol!
check_active_user!
unless actor check_project_accessibility!
return build_status_object(false, "No user or key was provided.") check_command_existence!(cmd)
end
if user && !user_access.allowed? check_geo_license!
return build_status_object(false, "Your account has been blocked.")
end
unless project && (user_access.can_read_project? || deploy_key_can_read_project? || geo_node_key)
return build_status_object(false, 'The project you were looking for could not be found.')
end
if Gitlab::Geo.secondary? && !Gitlab::Geo.license_allows?
return build_status_object(false, 'Your current license does not have GitLab Geo add-on enabled.')
end
case cmd case cmd
when *DOWNLOAD_COMMANDS when *DOWNLOAD_COMMANDS
...@@ -44,47 +42,43 @@ module Gitlab ...@@ -44,47 +42,43 @@ module Gitlab
push_access_check(changes) push_access_check(changes)
when *GIT_ANNEX_COMMANDS when *GIT_ANNEX_COMMANDS
git_annex_access_check(project, changes) git_annex_access_check(project, changes)
else
build_status_object(false, "The command you're trying to execute is not allowed.")
end end
build_status_object(true)
rescue UnauthorizedError => ex
build_status_object(false, ex.message)
end end
def download_access_check def download_access_check
if user if user
user_download_access_check user_download_access_check
elsif deploy_key || geo_node_key elsif deploy_key.nil? && geo_node_key.nil? && !Guest.can?(:download_code, project)
build_status_object(true) raise UnauthorizedError, ERROR_MESSAGES[:download]
else
raise 'Wrong actor'
end end
end end
def push_access_check(changes) def push_access_check(changes)
if project.repository_read_only? if project.repository_read_only?
return build_status_object(false, 'The repository is temporarily read-only. Please try again later.') raise UnauthorizedError, 'The repository is temporarily read-only. Please try again later.'
end end
if Gitlab::Geo.secondary? if Gitlab::Geo.secondary?
return build_status_object(false, "You can't push code on a secondary GitLab Geo node.") raise UnauthorizedError, "You can't push code on a secondary GitLab Geo node."
end end
return build_status_object(true) if git_annex_branch_sync?(changes) return if git_annex_branch_sync?(changes)
if user if user
user_push_access_check(changes) user_push_access_check(changes)
elsif deploy_key
build_status_object(false, "Deploy keys are not allowed to push code.")
else else
raise 'Wrong actor' raise UnauthorizedError, ERROR_MESSAGES[deploy_key ? :deploy_key : :upload]
end end
end end
def user_download_access_check def user_download_access_check
unless user_can_download_code? || build_can_download_code? unless user_can_download_code? || build_can_download_code?
return build_status_object(false, "You are not allowed to download code from this project.") raise UnauthorizedError, ERROR_MESSAGES[:download]
end end
build_status_object(true)
end end
def user_can_download_code? def user_can_download_code?
...@@ -97,20 +91,24 @@ module Gitlab ...@@ -97,20 +91,24 @@ module Gitlab
def user_push_access_check(changes) def user_push_access_check(changes)
unless authentication_abilities.include?(:push_code) unless authentication_abilities.include?(:push_code)
return build_status_object(false, "You are not allowed to upload code for this project.") raise UnauthorizedError, ERROR_MESSAGES[:upload]
end end
if changes.blank? if changes.blank?
return build_status_object(true) return # Allow access.
end end
return build_status_object(false, "A repository for this project does not exist yet.") unless project.repository.exists? unless project.repository.exists?
raise UnauthorizedError, ERROR_MESSAGES[:no_repo]
end
return build_status_object(false, Gitlab::RepositorySizeError.new(project).push_error) if project.above_size_limit? if project.above_size_limit?
raise UnauthorizedError, Gitlab::RepositorySizeError.new(project).push_error
end
if ::License.block_changes? if ::License.block_changes?
message = ::LicenseHelper.license_message(signed_in: true, is_admin: (user && user.is_admin?)) message = ::LicenseHelper.license_message(signed_in: true, is_admin: (user && user.is_admin?))
return build_status_object(false, message) raise UnauthorizedError, message
end end
changes_list = Gitlab::ChangesList.new(changes) changes_list = Gitlab::ChangesList.new(changes)
...@@ -122,7 +120,7 @@ module Gitlab ...@@ -122,7 +120,7 @@ module Gitlab
status = change_access_check(change) status = change_access_check(change)
unless status.allowed? unless status.allowed?
# If user does not have access to make at least one change - cancel all push # If user does not have access to make at least one change - cancel all push
return status raise UnauthorizedError, status.message
end end
if project.size_limit_enabled? if project.size_limit_enabled?
...@@ -131,10 +129,8 @@ module Gitlab ...@@ -131,10 +129,8 @@ module Gitlab
end end
if project.changes_will_exceed_size_limit?(push_size_in_bytes.to_mb) if project.changes_will_exceed_size_limit?(push_size_in_bytes.to_mb)
return build_status_object(false, Gitlab::RepositorySizeError.new(project).new_changes_error) raise UnauthorizedError, Gitlab::RepositorySizeError.new(project).new_changes_error
end end
build_status_object(true)
end end
def change_access_check(change) def change_access_check(change)
...@@ -145,12 +141,42 @@ module Gitlab ...@@ -145,12 +141,42 @@ module Gitlab
Gitlab::ProtocolAccess.allowed?(protocol) Gitlab::ProtocolAccess.allowed?(protocol)
end end
private
def check_protocol!
unless protocol_allowed?
raise UnauthorizedError, "Git access over #{protocol.upcase} is not allowed"
end
end
def check_active_user!
if user && !user_access.allowed?
raise UnauthorizedError, "Your account has been blocked."
end
end
def check_project_accessibility!
if project.blank? || !can_read_project?
raise UnauthorizedError, 'The project you were looking for could not be found.'
end
end
def check_command_existence!(cmd)
unless ALL_COMMANDS.include?(cmd)
raise UnauthorizedError, "The command you're trying to execute is not allowed."
end
end
def check_geo_license!
if Gitlab::Geo.secondary? && !Gitlab::Geo.license_allows?
raise UnauthorizedError, 'Your current license does not have GitLab Geo add-on enabled.'
end
end
def matching_merge_request?(newrev, branch_name) def matching_merge_request?(newrev, branch_name)
Checks::MatchingMergeRequest.new(newrev, branch_name, project).match? Checks::MatchingMergeRequest.new(newrev, branch_name, project).match?
end end
private
def protected_branch_action(oldrev, newrev, branch_name) def protected_branch_action(oldrev, newrev, branch_name)
# we dont allow force push to protected branch # we dont allow force push to protected branch
if forced_push?(oldrev, newrev) if forced_push?(oldrev, newrev)
...@@ -188,6 +214,18 @@ module Gitlab ...@@ -188,6 +214,18 @@ module Gitlab
end end
end end
def can_read_project?
if user
user_access.can_read_project?
elsif deploy_key
deploy_key_can_read_project?
elsif geo_node_key
true
else
Guest.can?(:read_project, project)
end
end
protected protected
def user def user
...@@ -211,24 +249,22 @@ module Gitlab ...@@ -211,24 +249,22 @@ module Gitlab
end end
def git_annex_access_check(project, changes) def git_annex_access_check(project, changes)
return build_status_object(false, "git-annex is disabled") unless Gitlab.config.gitlab_shell.git_annex_enabled raise UnauthorizedError, "git-annex is disabled" unless Gitlab.config.gitlab_shell.git_annex_enabled
unless user && user_access.allowed? unless user && user_access.allowed?
return build_status_object(false, "You don't have access") raise UnauthorizedError, "You don't have access"
end end
unless project.repository.exists? unless project.repository.exists?
return build_status_object(false, "Repository does not exist") raise UnauthorizedError, "Repository does not exist"
end end
if Gitlab::Geo.enabled? && Gitlab::Geo.secondary? if Gitlab::Geo.enabled? && Gitlab::Geo.secondary?
return build_status_object(false, "You can't use git-annex with a secondary GitLab Geo node.") raise UnauthorizedError, "You can't use git-annex with a secondary GitLab Geo node."
end end
if user.can?(:push_code, project) unless user.can?(:push_code, project)
build_status_object(true) raise UnauthorizedError, "You don't have permission"
else
build_status_object(false, "You don't have permission")
end end
end end
......
...@@ -70,13 +70,17 @@ FactoryGirl.define do ...@@ -70,13 +70,17 @@ FactoryGirl.define do
end end
after(:create) do |project, evaluator| after(:create) do |project, evaluator|
# Builds and MRs can't have higher visibility level than repository access level.
builds_access_level = [evaluator.builds_access_level, evaluator.repository_access_level].min
merge_requests_access_level = [evaluator.merge_requests_access_level, evaluator.repository_access_level].min
project.project_feature. project.project_feature.
update_attributes( update_attributes!(
wiki_access_level: evaluator.wiki_access_level, wiki_access_level: evaluator.wiki_access_level,
builds_access_level: evaluator.builds_access_level, builds_access_level: builds_access_level,
snippets_access_level: evaluator.snippets_access_level, snippets_access_level: evaluator.snippets_access_level,
issues_access_level: evaluator.issues_access_level, issues_access_level: evaluator.issues_access_level,
merge_requests_access_level: evaluator.merge_requests_access_level, merge_requests_access_level: merge_requests_access_level,
repository_access_level: evaluator.repository_access_level repository_access_level: evaluator.repository_access_level
) )
end end
......
...@@ -71,6 +71,7 @@ describe Gitlab::GitAccess, lib: true do ...@@ -71,6 +71,7 @@ describe Gitlab::GitAccess, lib: true do
context 'pull code' do context 'pull code' do
it { expect(subject.allowed?).to be_falsey } it { expect(subject.allowed?).to be_falsey }
it { expect(subject.message).to match(/You are not allowed to download code/) }
end end
end end
...@@ -82,6 +83,7 @@ describe Gitlab::GitAccess, lib: true do ...@@ -82,6 +83,7 @@ describe Gitlab::GitAccess, lib: true do
context 'pull code' do context 'pull code' do
it { expect(subject.allowed?).to be_falsey } it { expect(subject.allowed?).to be_falsey }
it { expect(subject.message).to match(/Your account has been blocked/) }
end end
end end
...@@ -89,6 +91,29 @@ describe Gitlab::GitAccess, lib: true do ...@@ -89,6 +91,29 @@ describe Gitlab::GitAccess, lib: true do
context 'pull code' do context 'pull code' do
it { expect(subject.allowed?).to be_falsey } it { expect(subject.allowed?).to be_falsey }
end end
context 'when project is public' do
let(:public_project) { create(:project, :public) }
let(:guest_access) { Gitlab::GitAccess.new(nil, public_project, 'web', authentication_abilities: []) }
subject { guest_access.check('git-upload-pack', '_any') }
context 'when repository is enabled' do
it 'give access to download code' do
public_project.project_feature.update_attribute(:repository_access_level, ProjectFeature::ENABLED)
expect(subject.allowed?).to be_truthy
end
end
context 'when repository is disabled' do
it 'does not give access to download code' do
public_project.project_feature.update_attribute(:repository_access_level, ProjectFeature::DISABLED)
expect(subject.allowed?).to be_falsey
expect(subject.message).to match(/You are not allowed to download code/)
end
end
end
end end
describe 'deploy key permissions' do describe 'deploy key permissions' do
...@@ -131,7 +156,7 @@ describe Gitlab::GitAccess, lib: true do ...@@ -131,7 +156,7 @@ describe Gitlab::GitAccess, lib: true do
context 'pull code' do context 'pull code' do
subject { access.download_access_check } subject { access.download_access_check }
it { expect(subject.allowed?).to be_truthy } it { expect { subject }.not_to raise_error }
end end
end end
...@@ -142,7 +167,7 @@ describe Gitlab::GitAccess, lib: true do ...@@ -142,7 +167,7 @@ describe Gitlab::GitAccess, lib: true do
let(:project) { create(:project, namespace: user.namespace) } let(:project) { create(:project, namespace: user.namespace) }
context 'pull code' do context 'pull code' do
it { expect(subject).to be_allowed } it { expect { subject }.not_to raise_error }
end end
end end
...@@ -150,7 +175,7 @@ describe Gitlab::GitAccess, lib: true do ...@@ -150,7 +175,7 @@ describe Gitlab::GitAccess, lib: true do
before { project.team << [user, :reporter] } before { project.team << [user, :reporter] }
context 'pull code' do context 'pull code' do
it { expect(subject).to be_allowed } it { expect { subject }.not_to raise_error }
end end
end end
...@@ -161,13 +186,13 @@ describe Gitlab::GitAccess, lib: true do ...@@ -161,13 +186,13 @@ describe Gitlab::GitAccess, lib: true do
before { project.team << [user, :reporter] } before { project.team << [user, :reporter] }
context 'pull code' do context 'pull code' do
it { expect(subject).to be_allowed } it { expect { subject }.not_to raise_error }
end end
end end
context 'when is not member of the project' do context 'when is not member of the project' do
context 'pull code' do context 'pull code' do
it { expect(subject).not_to be_allowed } it { expect { subject }.not_to raise_error }
end end
end end
end end
...@@ -224,7 +249,13 @@ describe Gitlab::GitAccess, lib: true do ...@@ -224,7 +249,13 @@ describe Gitlab::GitAccess, lib: true do
context action do context action do
subject { access.push_access_check(changes[action]) } subject { access.push_access_check(changes[action]) }
it { expect(subject.allowed?).to allowed ? be_truthy : be_falsey } it do
if allowed
expect { subject }.not_to raise_error
else
expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError)
end
end
end end
end end
end end
...@@ -245,8 +276,14 @@ describe Gitlab::GitAccess, lib: true do ...@@ -245,8 +276,14 @@ describe Gitlab::GitAccess, lib: true do
permissions_matrix[role].each do |action, allowed| permissions_matrix[role].each do |action, allowed|
context action do context action do
subject { access.push_access_check(changes[action]) } subject { access.push_access_check(changes[action]) }
it { expect(subject.allowed?).to allowed ? be_truthy : be_falsey } it do
if allowed
expect { subject }.not_to raise_error
else
expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError)
end
end
end end
end end
end end
...@@ -501,20 +538,20 @@ describe Gitlab::GitAccess, lib: true do ...@@ -501,20 +538,20 @@ describe Gitlab::GitAccess, lib: true do
allow(Gitlab::Geo).to receive(:secondary?) { true } allow(Gitlab::Geo).to receive(:secondary?) { true }
end end
it { expect(access.push_access_check(git_annex_changes)).not_to be_allowed } it { expect { access.push_access_check(git_annex_changes) }.to raise_error(described_class::UnauthorizedError) }
end end
describe 'and git hooks unset' do describe 'and git hooks unset' do
describe 'git annex enabled' do describe 'git annex enabled' do
before { allow(Gitlab.config.gitlab_shell).to receive(:git_annex_enabled).and_return(true) } before { allow(Gitlab.config.gitlab_shell).to receive(:git_annex_enabled).and_return(true) }
it { expect(access.push_access_check(git_annex_changes)).to be_allowed } it { expect { access.push_access_check(git_annex_changes) }.not_to raise_error }
end end
describe 'git annex disabled' do describe 'git annex disabled' do
before { allow(Gitlab.config.gitlab_shell).to receive(:git_annex_enabled).and_return(false) } before { allow(Gitlab.config.gitlab_shell).to receive(:git_annex_enabled).and_return(false) }
it { expect(access.push_access_check(git_annex_changes)).to be_allowed } it { expect { access.push_access_check(git_annex_changes) }.not_to raise_error }
end end
end end
...@@ -529,7 +566,7 @@ describe Gitlab::GitAccess, lib: true do ...@@ -529,7 +566,7 @@ describe Gitlab::GitAccess, lib: true do
describe 'git annex enabled' do describe 'git annex enabled' do
before { allow(Gitlab.config.gitlab_shell).to receive(:git_annex_enabled).and_return(true) } before { allow(Gitlab.config.gitlab_shell).to receive(:git_annex_enabled).and_return(true) }
it { expect(access.push_access_check(git_annex_changes)).to be_allowed } it { expect { access.push_access_check(git_annex_changes) }.not_to raise_error }
end end
describe 'git annex enabled, push to master branch' do describe 'git annex enabled, push to master branch' do
...@@ -538,7 +575,7 @@ describe Gitlab::GitAccess, lib: true do ...@@ -538,7 +575,7 @@ describe Gitlab::GitAccess, lib: true do
allow_any_instance_of(Commit).to receive(:safe_message) { 'git-annex in me@host:~/repo' } allow_any_instance_of(Commit).to receive(:safe_message) { 'git-annex in me@host:~/repo' }
end end
it { expect(access.push_access_check(git_annex_master_changes)).to be_allowed } it { expect { access.push_access_check(git_annex_master_changes) }.not_to raise_error }
end end
describe 'git annex disabled' do describe 'git annex disabled' do
...@@ -546,7 +583,7 @@ describe Gitlab::GitAccess, lib: true do ...@@ -546,7 +583,7 @@ describe Gitlab::GitAccess, lib: true do
allow(Gitlab.config.gitlab_shell).to receive(:git_annex_enabled).and_return(false) allow(Gitlab.config.gitlab_shell).to receive(:git_annex_enabled).and_return(false)
end end
it { expect(access.push_access_check(git_annex_changes)).not_to be_allowed } it { expect { access.push_access_check(git_annex_changes) }.to raise_error(described_class::UnauthorizedError) }
end end
end end
...@@ -560,7 +597,7 @@ describe Gitlab::GitAccess, lib: true do ...@@ -560,7 +597,7 @@ describe Gitlab::GitAccess, lib: true do
before { allow(Gitlab.config.gitlab_shell).to receive(:git_annex_enabled).and_return(true) } before { allow(Gitlab.config.gitlab_shell).to receive(:git_annex_enabled).and_return(true) }
it { expect(access.check('git-annex-shell', git_annex_changes).allowed?).to be_truthy } it { expect(access.check('git-annex-shell', git_annex_changes).allowed?).to be_truthy }
it { expect(access.push_access_check(git_annex_changes)).to be_allowed } it { expect { access.push_access_check(git_annex_changes) }.not_to raise_error }
end end
describe 'git annex disabled' do describe 'git annex disabled' do
...@@ -569,7 +606,7 @@ describe Gitlab::GitAccess, lib: true do ...@@ -569,7 +606,7 @@ describe Gitlab::GitAccess, lib: true do
end end
it { expect(access.check('git-annex-shell', git_annex_changes).allowed?).to be_falsey } it { expect(access.check('git-annex-shell', git_annex_changes).allowed?).to be_falsey }
it { expect(access.push_access_check(git_annex_changes)).not_to be_allowed } it { expect { access.push_access_check(git_annex_changes) }.to raise_error(described_class::UnauthorizedError) }
end end
end end
end end
...@@ -586,19 +623,21 @@ describe Gitlab::GitAccess, lib: true do ...@@ -586,19 +623,21 @@ describe Gitlab::GitAccess, lib: true do
describe "author email check" do describe "author email check" do
it 'returns true' do it 'returns true' do
expect(access.push_access_check('6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/master')).to be_truthy expect { access.push_access_check('6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/master') }.not_to raise_error
end end
it 'returns false' do it 'returns false' do
project.create_push_rule project.create_push_rule
project.push_rule.update(commit_message_regex: "@only.com") project.push_rule.update(commit_message_regex: "@only.com")
expect(access.push_access_check('6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/master')).not_to be_allowed
expect { access.push_access_check('6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/master') }.to raise_error(described_class::UnauthorizedError)
end end
it 'returns true for tags' do it 'returns true for tags' do
project.create_push_rule project.create_push_rule
project.push_rule.update(commit_message_regex: "@only.com") project.push_rule.update(commit_message_regex: "@only.com")
expect(access.push_access_check('6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/tags/v1')).to be_allowed
expect { access.push_access_check('6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/tags/v1') }.not_to raise_error
end end
it 'allows githook for new branch with an old bad commit' do it 'allows githook for new branch with an old bad commit' do
...@@ -611,7 +650,7 @@ describe Gitlab::GitAccess, lib: true do ...@@ -611,7 +650,7 @@ describe Gitlab::GitAccess, lib: true do
project.push_rule.update(commit_message_regex: "Change some files") project.push_rule.update(commit_message_regex: "Change some files")
# push to new branch, so use a blank old rev and new ref # push to new branch, so use a blank old rev and new ref
expect(access.push_access_check("#{Gitlab::Git::BLANK_SHA} 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/new-branch")).to be_allowed expect { access.push_access_check("#{Gitlab::Git::BLANK_SHA} 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/new-branch") }.not_to raise_error
end end
it 'allows githook for any change with an old bad commit' do it 'allows githook for any change with an old bad commit' do
...@@ -624,7 +663,7 @@ describe Gitlab::GitAccess, lib: true do ...@@ -624,7 +663,7 @@ describe Gitlab::GitAccess, lib: true do
project.push_rule.update(commit_message_regex: "Change some files") project.push_rule.update(commit_message_regex: "Change some files")
# push to new branch, so use a blank old rev and new ref # push to new branch, so use a blank old rev and new ref
expect(access.push_access_check('6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/master')).to be_allowed expect { access.push_access_check('6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/master') }.not_to raise_error
end end
it 'does not allow any change from Web UI with bad commit' do it 'does not allow any change from Web UI with bad commit' do
...@@ -639,7 +678,7 @@ describe Gitlab::GitAccess, lib: true do ...@@ -639,7 +678,7 @@ describe Gitlab::GitAccess, lib: true do
project.push_rule.update(commit_message_regex: "Change some files") project.push_rule.update(commit_message_regex: "Change some files")
# push to new branch, so use a blank old rev and new ref # push to new branch, so use a blank old rev and new ref
expect(access.push_access_check('6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/master')).not_to be_allowed expect { access.push_access_check('6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/master') }.to raise_error(described_class::UnauthorizedError)
end end
end end
...@@ -650,12 +689,13 @@ describe Gitlab::GitAccess, lib: true do ...@@ -650,12 +689,13 @@ describe Gitlab::GitAccess, lib: true do
end end
it 'returns false for non-member user' do it 'returns false for non-member user' do
expect(access.push_access_check('6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/master')).not_to be_allowed expect { access.push_access_check('6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/master') }.to raise_error(described_class::UnauthorizedError)
end end
it 'returns true if committer is a gitlab member' do it 'returns true if committer is a gitlab member' do
create(:user, email: 'dmitriy.zaporozhets@gmail.com') create(:user, email: 'dmitriy.zaporozhets@gmail.com')
expect(access.push_access_check('6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/master')).to be_allowed
expect { access.push_access_check('6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/master') }.not_to raise_error
end end
end end
...@@ -669,13 +709,15 @@ describe Gitlab::GitAccess, lib: true do ...@@ -669,13 +709,15 @@ describe Gitlab::GitAccess, lib: true do
it 'returns false when filename is prohibited' do it 'returns false when filename is prohibited' do
project.create_push_rule project.create_push_rule
project.push_rule.update(file_name_regex: "jpg$") project.push_rule.update(file_name_regex: "jpg$")
expect(access.push_access_check('913c66a37b4a45b9769037c55c2d238bd0942d2e 33f3729a45c02fc67d00adb1b8bca394b0e761d9 refs/heads/master')).not_to be_allowed
expect { access.push_access_check('913c66a37b4a45b9769037c55c2d238bd0942d2e 33f3729a45c02fc67d00adb1b8bca394b0e761d9 refs/heads/master') }.to raise_error(described_class::UnauthorizedError)
end end
it 'returns true if file name is allowed' do it 'returns true if file name is allowed' do
project.create_push_rule project.create_push_rule
project.push_rule.update(file_name_regex: "exe$") project.push_rule.update(file_name_regex: "exe$")
expect(access.push_access_check('913c66a37b4a45b9769037c55c2d238bd0942d2e 33f3729a45c02fc67d00adb1b8bca394b0e761d9 refs/heads/master')).to be_allowed
expect { access.push_access_check('913c66a37b4a45b9769037c55c2d238bd0942d2e 33f3729a45c02fc67d00adb1b8bca394b0e761d9 refs/heads/master') }.not_to raise_error
end end
end end
...@@ -687,20 +729,23 @@ describe Gitlab::GitAccess, lib: true do ...@@ -687,20 +729,23 @@ describe Gitlab::GitAccess, lib: true do
it "returns false when size is too large" do it "returns false when size is too large" do
project.create_push_rule project.create_push_rule
project.push_rule.update(max_file_size: 1) project.push_rule.update(max_file_size: 1)
expect(access.push_access_check('cfe32cf61b73a0d5e9f13e774abde7ff789b1660 913c66a37b4a45b9769037c55c2d238bd0942d2e refs/heads/master')).not_to be_allowed
expect { access.push_access_check('cfe32cf61b73a0d5e9f13e774abde7ff789b1660 913c66a37b4a45b9769037c55c2d238bd0942d2e refs/heads/master') }.to raise_error(described_class::UnauthorizedError)
end end
it "returns true when size is allowed" do it "returns true when size is allowed" do
project.create_push_rule project.create_push_rule
project.push_rule.update(max_file_size: 2) project.push_rule.update(max_file_size: 2)
expect(access.push_access_check('cfe32cf61b73a0d5e9f13e774abde7ff789b1660 913c66a37b4a45b9769037c55c2d238bd0942d2e refs/heads/master')).to be_allowed
expect { access.push_access_check('cfe32cf61b73a0d5e9f13e774abde7ff789b1660 913c66a37b4a45b9769037c55c2d238bd0942d2e refs/heads/master') }.not_to raise_error
end end
it "returns true when size is nil" do it "returns true when size is nil" do
allow_any_instance_of(Gitlab::Git::Blob).to receive(:size).and_return(nil) allow_any_instance_of(Gitlab::Git::Blob).to receive(:size).and_return(nil)
project.create_push_rule project.create_push_rule
project.push_rule.update(max_file_size: 2) project.push_rule.update(max_file_size: 2)
expect(access.push_access_check('cfe32cf61b73a0d5e9f13e774abde7ff789b1660 913c66a37b4a45b9769037c55c2d238bd0942d2e refs/heads/master')).to be_allowed
expect { access.push_access_check('cfe32cf61b73a0d5e9f13e774abde7ff789b1660 913c66a37b4a45b9769037c55c2d238bd0942d2e refs/heads/master') }.not_to raise_error
end end
end end
...@@ -712,13 +757,13 @@ describe Gitlab::GitAccess, lib: true do ...@@ -712,13 +757,13 @@ describe Gitlab::GitAccess, lib: true do
it 'returns false when blob is too big' do it 'returns false when blob is too big' do
allow_any_instance_of(Gitlab::Git::Blob).to receive(:size).and_return(100.megabytes.to_i) allow_any_instance_of(Gitlab::Git::Blob).to receive(:size).and_return(100.megabytes.to_i)
expect(access.push_access_check('cfe32cf61b73a0d5e9f13e774abde7ff789b1660 913c66a37b4a45b9769037c55c2d238bd0942d2e refs/heads/master')).not_to be_allowed expect { access.push_access_check('cfe32cf61b73a0d5e9f13e774abde7ff789b1660 913c66a37b4a45b9769037c55c2d238bd0942d2e refs/heads/master') }.to raise_error(described_class::UnauthorizedError)
end end
it 'returns true when blob is just right' do it 'returns true when blob is just right' do
allow_any_instance_of(Gitlab::Git::Blob).to receive(:size).and_return(2.megabytes.to_i) allow_any_instance_of(Gitlab::Git::Blob).to receive(:size).and_return(2.megabytes.to_i)
expect(access.push_access_check('cfe32cf61b73a0d5e9f13e774abde7ff789b1660 913c66a37b4a45b9769037c55c2d238bd0942d2e refs/heads/master')).to be_allowed expect { access.push_access_check('cfe32cf61b73a0d5e9f13e774abde7ff789b1660 913c66a37b4a45b9769037c55c2d238bd0942d2e refs/heads/master') }.not_to raise_error
end end
end end
end end
......
...@@ -20,7 +20,7 @@ describe Gitlab::GitAccessWiki, lib: true do ...@@ -20,7 +20,7 @@ describe Gitlab::GitAccessWiki, lib: true do
project.team << [user, :developer] project.team << [user, :developer]
end end
subject { access.push_access_check(changes) } subject { access.check('git-receive-pack', changes) }
it { expect(subject.allowed?).to be_truthy } it { expect(subject.allowed?).to be_truthy }
......
require 'spec_helper'
describe Guest, lib: true do
let(:public_project) { create(:project, :public) }
let(:private_project) { create(:project, :private) }
let(:internal_project) { create(:project, :internal) }
describe '.can_pull?' do
context 'when project is private' do
it 'does not allow to pull the repo' do
expect(Guest.can?(:download_code, private_project)).to eq(false)
end
end
context 'when project is internal' do
it 'does not allow to pull the repo' do
expect(Guest.can?(:download_code, internal_project)).to eq(false)
end
end
context 'when project is public' do
context 'when repository is disabled' do
it 'does not allow to pull the repo' do
public_project.project_feature.update_attribute(:repository_access_level, ProjectFeature::DISABLED)
expect(Guest.can?(:download_code, public_project)).to eq(false)
end
end
context 'when repository is accessible only by team members' do
it 'does not allow to pull the repo' do
public_project.project_feature.update_attribute(:repository_access_level, ProjectFeature::PRIVATE)
expect(Guest.can?(:download_code, public_project)).to eq(false)
end
end
context 'when repository is enabled' do
it 'allows to pull the repo' do
public_project.project_feature.update_attribute(:repository_access_level, ProjectFeature::ENABLED)
expect(Guest.can?(:download_code, public_project)).to eq(true)
end
end
end
end
end
...@@ -115,6 +115,38 @@ describe 'Git HTTP requests', lib: true do ...@@ -115,6 +115,38 @@ describe 'Git HTTP requests', lib: true do
end.to raise_error(JWT::DecodeError) end.to raise_error(JWT::DecodeError)
end end
end end
context 'when the repo is public' do
context 'but the repo is disabled' do
it 'does not allow to clone the repo' do
project = create(:project, :public, repository_access_level: ProjectFeature::DISABLED)
download("#{project.path_with_namespace}.git", {}) do |response|
expect(response).to have_http_status(:unauthorized)
end
end
end
context 'but the repo is enabled' do
it 'allows to clone the repo' do
project = create(:project, :public, repository_access_level: ProjectFeature::ENABLED)
download("#{project.path_with_namespace}.git", {}) do |response|
expect(response).to have_http_status(:ok)
end
end
end
context 'but only project members are allowed' do
it 'does not allow to clone the repo' do
project = create(:project, :public, repository_access_level: ProjectFeature::PRIVATE)
download("#{project.path_with_namespace}.git", {}) do |response|
expect(response).to have_http_status(:unauthorized)
end
end
end
end
end end
context "when Kerberos token is provided" do context "when Kerberos token is provided" do
......
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