Commit 5578506e authored by Douwe Maan's avatar Douwe Maan

Merge branch 'mk-fix-git-over-http-rejections' into 'master'

Fix Git-over-HTTP rejections

See merge request !11398
parents 059b9627 ef4e9135
......@@ -106,4 +106,8 @@ module LfsRequest
def objects
@objects ||= (params[:objects] || []).to_a
end
def has_authentication_ability?(capability)
(authentication_abilities || []).include?(capability)
end
end
......@@ -128,32 +128,10 @@ class Projects::GitHttpClientController < Projects::ApplicationController
@authentication_result = Gitlab::Auth.find_for_git_client(
login, password, project: project, ip: request.ip)
return false unless @authentication_result.success?
if download_request?
authentication_has_download_access?
else
authentication_has_upload_access?
end
@authentication_result.success?
end
def ci?
authentication_result.ci?(project)
end
def authentication_has_download_access?
has_authentication_ability?(:download_code) || has_authentication_ability?(:build_download_code)
end
def authentication_has_upload_access?
has_authentication_ability?(:push_code)
end
def has_authentication_ability?(capability)
(authentication_abilities || []).include?(capability)
end
def authentication_project
authentication_result.project
end
end
class Projects::GitHttpController < Projects::GitHttpClientController
include WorkhorseRequest
before_action :access_check
rescue_from Gitlab::GitAccess::UnauthorizedError, with: :render_403
rescue_from Gitlab::GitAccess::NotFoundError, with: :render_404
# GET /foo/bar.git/info/refs?service=git-upload-pack (git pull)
# GET /foo/bar.git/info/refs?service=git-receive-pack (git push)
def info_refs
if upload_pack? && upload_pack_allowed?
log_user_activity
render_ok
elsif receive_pack? && receive_pack_allowed?
render_ok
elsif http_blocked?
render_http_not_allowed
else
render_denied
end
log_user_activity if upload_pack?
render_ok
end
# POST /foo/bar.git/git-upload-pack (git pull)
def git_upload_pack
if upload_pack? && upload_pack_allowed?
render_ok
else
render_denied
end
render_ok
end
# POST /foo/bar.git/git-receive-pack" (git push)
def git_receive_pack
if receive_pack? && receive_pack_allowed?
render_ok
else
render_denied
end
render_ok
end
private
......@@ -45,10 +34,6 @@ class Projects::GitHttpController < Projects::GitHttpClientController
git_command == 'git-upload-pack'
end
def receive_pack?
git_command == 'git-receive-pack'
end
def git_command
if action_name == 'info_refs'
params[:service]
......@@ -62,47 +47,27 @@ class Projects::GitHttpController < Projects::GitHttpClientController
render json: Gitlab::Workhorse.git_http_ok(repository, wiki?, user, action_name)
end
def render_http_not_allowed
render plain: access_check.message, status: :forbidden
def render_403(exception)
render plain: exception.message, status: :forbidden
end
def render_denied
if user && can?(user, :read_project, project)
render plain: access_denied_message, status: :forbidden
else
# Do not leak information about project existence
render_not_found
end
end
def access_denied_message
'Access denied'
def render_404(exception)
render plain: exception.message, status: :not_found
end
def upload_pack_allowed?
return false unless Gitlab.config.gitlab_shell.upload_pack
access_check.allowed? || ci?
def access
@access ||= access_klass.new(access_actor, project, 'http', authentication_abilities: authentication_abilities)
end
def access
@access ||= access_klass.new(user, project, 'http', authentication_abilities: authentication_abilities)
def access_actor
return user if user
return :ci if ci?
end
def access_check
# Use the magic string '_any' to indicate we do not know what the
# changes are. This is also what gitlab-shell does.
@access_check ||= access.check(git_command, '_any')
end
def http_blocked?
!access.protocol_allowed?
end
def receive_pack_allowed?
return false unless Gitlab.config.gitlab_shell.receive_pack
access_check.allowed?
access.check(git_command, '_any')
end
def access_klass
......
---
title: Fix Git-over-HTTP error statuses and improve error messages
merge_request: 11398
author:
......@@ -42,6 +42,22 @@ module API
@project, @wiki = Gitlab::RepoPath.parse(params[:project])
end
end
# Project id to pass between components that don't share/don't have
# access to the same filesystem mounts
def gl_repository
Gitlab::GlRepository.gl_repository(project, wiki?)
end
# Return the repository full path so that gitlab-shell has it when
# handling ssh commands
def repository_path
if wiki?
project.wiki.repository.path_to_repo
else
project.repository.path_to_repo
end
end
end
end
end
......@@ -32,31 +32,23 @@ module API
actor.update_last_used_at if actor.is_a?(Key)
access_checker = wiki? ? Gitlab::GitAccessWiki : Gitlab::GitAccess
access_status = access_checker
access_checker_klass = wiki? ? Gitlab::GitAccessWiki : Gitlab::GitAccess
access_checker = access_checker_klass
.new(actor, project, protocol, authentication_abilities: ssh_authentication_abilities)
.check(params[:action], params[:changes])
response = { status: access_status.status, message: access_status.message }
if access_status.status
log_user_activity(actor)
# Project id to pass between components that don't share/don't have
# access to the same filesystem mounts
response[:gl_repository] = Gitlab::GlRepository.gl_repository(project, wiki?)
# Return the repository full path so that gitlab-shell has it when
# handling ssh commands
response[:repository_path] =
if wiki?
project.wiki.repository.path_to_repo
else
project.repository.path_to_repo
end
begin
access_checker.check(params[:action], params[:changes])
rescue Gitlab::GitAccess::UnauthorizedError, Gitlab::GitAccess::NotFoundError => e
return { status: false, message: e.message }
end
response
log_user_activity(actor)
{
status: true,
gl_repository: gl_repository,
repository_path: repository_path
}
end
post "/lfs_authenticate" do
......
module Gitlab
module Checks
class ChangeAccess
ERROR_MESSAGES = {
push_code: 'You are not allowed to push code to this project.',
delete_default_branch: 'The default branch of a project cannot be deleted.',
force_push_protected_branch: 'You are not allowed to force push code to a protected branch on this project.',
non_master_delete_protected_branch: 'You are not allowed to delete protected branches from this project. Only a project master or owner can delete a protected branch.',
non_web_delete_protected_branch: 'You can only delete protected branches using the web interface.',
merge_protected_branch: 'You are not allowed to merge code into protected branches on this project.',
push_protected_branch: 'You are not allowed to push code to protected branches on this project.',
change_existing_tags: 'You are not allowed to change existing tags on this project.',
update_protected_tag: 'Protected tags cannot be updated.',
delete_protected_tag: 'Protected tags cannot be deleted.',
create_protected_tag: 'You are not allowed to create this tag as it is protected.'
}.freeze
attr_reader :user_access, :project, :skip_authorization, :protocol
def initialize(
......@@ -17,22 +31,20 @@ module Gitlab
end
def exec
return GitAccessStatus.new(true) if skip_authorization
return true if skip_authorization
error = push_checks || branch_checks || tag_checks
push_checks
branch_checks
tag_checks
if error
GitAccessStatus.new(false, error)
else
GitAccessStatus.new(true)
end
true
end
protected
def push_checks
if user_access.cannot_do_action?(:push_code)
"You are not allowed to push code to this project."
raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:push_code]
end
end
......@@ -40,7 +52,7 @@ module Gitlab
return unless @branch_name
if deletion? && @branch_name == project.default_branch
return "The default branch of a project cannot be deleted."
raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:delete_default_branch]
end
protected_branch_checks
......@@ -50,7 +62,7 @@ module Gitlab
return unless ProtectedBranch.protected?(project, @branch_name)
if forced_push?
return "You are not allowed to force push code to a protected branch on this project."
raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:force_push_protected_branch]
end
if deletion?
......@@ -62,22 +74,22 @@ module Gitlab
def protected_branch_deletion_checks
unless user_access.can_delete_branch?(@branch_name)
return 'You are not allowed to delete protected branches from this project. Only a project master or owner can delete a protected branch.'
raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:non_master_delete_protected_branch]
end
unless protocol == 'web'
'You can only delete protected branches using the web interface.'
raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:non_web_delete_protected_branch]
end
end
def protected_branch_push_checks
if matching_merge_request?
unless user_access.can_merge_to_branch?(@branch_name) || user_access.can_push_to_branch?(@branch_name)
"You are not allowed to merge code into protected branches on this project."
raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:merge_protected_branch]
end
else
unless user_access.can_push_to_branch?(@branch_name)
"You are not allowed to push code to protected branches on this project."
raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:push_protected_branch]
end
end
end
......@@ -86,7 +98,7 @@ module Gitlab
return unless @tag_name
if tag_exists? && user_access.cannot_do_action?(:admin_project)
return "You are not allowed to change existing tags on this project."
raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:change_existing_tags]
end
protected_tag_checks
......@@ -95,11 +107,11 @@ module Gitlab
def protected_tag_checks
return unless ProtectedTag.protected?(project, @tag_name)
return "Protected tags cannot be updated." if update?
return "Protected tags cannot be deleted." if deletion?
raise(GitAccess::UnauthorizedError, ERROR_MESSAGES[:update_protected_tag]) if update?
raise(GitAccess::UnauthorizedError, ERROR_MESSAGES[:delete_protected_tag]) if deletion?
unless user_access.can_create_tag?(@tag_name)
return "You are not allowed to create this tag as it is protected."
raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:create_protected_tag]
end
end
......
module Gitlab
# For backwards compatibility, generic CI (which is a build without a user) is
# allowed to :build_download_code without any other checks.
class CiAccess
def can_do_action?(action)
action == :build_download_code
end
end
end
......@@ -3,33 +3,39 @@
module Gitlab
class GitAccess
UnauthorizedError = Class.new(StandardError)
NotFoundError = Class.new(StandardError)
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_upload:
'This deploy key does not have write access to this project.',
no_repo: 'A repository for this project does not exist yet.'
no_repo: 'A repository for this project does not exist yet.',
project_not_found: 'The project you were looking for could not be found.',
account_blocked: 'Your account has been blocked.',
command_not_allowed: "The command you're trying to execute is not allowed.",
upload_pack_disabled_over_http: 'Pulling over HTTP is not allowed.',
receive_pack_disabled_over_http: 'Pushing over HTTP is not allowed.'
}.freeze
DOWNLOAD_COMMANDS = %w{ git-upload-pack git-upload-archive }.freeze
PUSH_COMMANDS = %w{ git-receive-pack }.freeze
ALL_COMMANDS = DOWNLOAD_COMMANDS + PUSH_COMMANDS
attr_reader :actor, :project, :protocol, :user_access, :authentication_abilities
attr_reader :actor, :project, :protocol, :authentication_abilities
def initialize(actor, project, protocol, authentication_abilities:)
@actor = actor
@project = project
@protocol = protocol
@authentication_abilities = authentication_abilities
@user_access = UserAccess.new(user, project: project)
end
def check(cmd, changes)
check_protocol!
check_active_user!
check_project_accessibility!
check_command_disabled!(cmd)
check_command_existence!(cmd)
check_repository_existence!
......@@ -40,9 +46,7 @@ module Gitlab
check_push_access!(changes)
end
build_status_object(true)
rescue UnauthorizedError => ex
build_status_object(false, ex.message)
true
end
def guest_can_download_code?
......@@ -73,19 +77,39 @@ module Gitlab
return if deploy_key?
if user && !user_access.allowed?
raise UnauthorizedError, "Your account has been blocked."
raise UnauthorizedError, ERROR_MESSAGES[:account_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.'
raise NotFoundError, ERROR_MESSAGES[:project_not_found]
end
end
def check_command_disabled!(cmd)
if upload_pack?(cmd)
check_upload_pack_disabled!
elsif receive_pack?(cmd)
check_receive_pack_disabled!
end
end
def check_upload_pack_disabled!
if http? && upload_pack_disabled_over_http?
raise UnauthorizedError, ERROR_MESSAGES[:upload_pack_disabled_over_http]
end
end
def check_receive_pack_disabled!
if http? && receive_pack_disabled_over_http?
raise UnauthorizedError, ERROR_MESSAGES[:receive_pack_disabled_over_http]
end
end
def check_command_existence!(cmd)
unless ALL_COMMANDS.include?(cmd)
raise UnauthorizedError, "The command you're trying to execute is not allowed."
raise UnauthorizedError, ERROR_MESSAGES[:command_not_allowed]
end
end
......@@ -138,11 +162,9 @@ module Gitlab
# Iterate over all changes to find if user allowed all of them to be applied
changes_list.each do |change|
status = check_single_change_access(change)
unless status.allowed?
# If user does not have access to make at least one change - cancel all push
raise UnauthorizedError, status.message
end
# If user does not have access to make at least one change, cancel all
# push by allowing the exception to bubble up
check_single_change_access(change)
end
end
......@@ -168,14 +190,40 @@ module Gitlab
actor.is_a?(DeployKey)
end
def ci?
actor == :ci
end
def can_read_project?
if deploy_key
if deploy_key?
deploy_key.has_access_to?(project)
elsif user
user.can?(:read_project, project)
elsif ci?
true # allow CI (build without a user) for backwards compatibility
end || Guest.can?(:read_project, project)
end
def http?
protocol == 'http'
end
def upload_pack?(command)
command == 'git-upload-pack'
end
def receive_pack?(command)
command == 'git-receive-pack'
end
def upload_pack_disabled_over_http?
!Gitlab.config.gitlab_shell.upload_pack
end
def receive_pack_disabled_over_http?
!Gitlab.config.gitlab_shell.receive_pack
end
protected
def user
......@@ -185,15 +233,19 @@ module Gitlab
case actor
when User
actor
when DeployKey
nil
when Key
actor.user
actor.user unless actor.is_a?(DeployKey)
when :ci
nil
end
end
def build_status_object(status, message = '')
Gitlab::GitAccessStatus.new(status, message)
def user_access
@user_access ||= if ci?
CiAccess.new
else
UserAccess.new(user, project: project)
end
end
end
end
module Gitlab
class GitAccessStatus
attr_accessor :status, :message
alias_method :allowed?, :status
def initialize(status, message = '')
@status = status
@message = message
end
def to_json(opts = nil)
{ status: @status, message: @message }.to_json(opts)
end
end
end
module Gitlab
class GitAccessWiki < GitAccess
ERROR_MESSAGES = {
write_to_wiki: "You are not allowed to write to this project's wiki."
}.freeze
def guest_can_download_code?
Guest.can?(:download_wiki_code, project)
end
......@@ -9,11 +13,11 @@ module Gitlab
end
def check_single_change_access(change)
if user_access.can_do_action?(:create_wiki)
build_status_object(true)
else
build_status_object(false, "You are not allowed to write to this project's wiki.")
unless user_access.can_do_action?(:create_wiki)
raise UnauthorizedError, ERROR_MESSAGES[:write_to_wiki]
end
true
end
end
end
......@@ -23,29 +23,27 @@ describe Gitlab::Checks::ChangeAccess, lib: true do
before { project.add_developer(user) }
context 'without failed checks' do
it "doesn't return any error" do
expect(subject.status).to be(true)
it "doesn't raise an error" do
expect { subject }.not_to raise_error
end
end
context 'when the user is not allowed to push code' do
it 'returns an error' do
it 'raises an error' do
expect(user_access).to receive(:can_do_action?).with(:push_code).and_return(false)
expect(subject.status).to be(false)
expect(subject.message).to eq('You are not allowed to push code to this project.')
expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to push code to this project.')
end
end
context 'tags check' do
let(:ref) { 'refs/tags/v1.0.0' }
it 'returns an error if the user is not allowed to update tags' do
it 'raises an error if the user is not allowed to update tags' do
allow(user_access).to receive(:can_do_action?).with(:push_code).and_return(true)
expect(user_access).to receive(:can_do_action?).with(:admin_project).and_return(false)
expect(subject.status).to be(false)
expect(subject.message).to eq('You are not allowed to change existing tags on this project.')
expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to change existing tags on this project.')
end
context 'with protected tag' do
......@@ -59,8 +57,7 @@ describe Gitlab::Checks::ChangeAccess, lib: true do
let(:newrev) { '0000000000000000000000000000000000000000' }
it 'is prevented' do
expect(subject.status).to be(false)
expect(subject.message).to include('cannot be deleted')
expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError, /cannot be deleted/)
end
end
......@@ -69,8 +66,7 @@ describe Gitlab::Checks::ChangeAccess, lib: true do
let(:newrev) { '54fcc214b94e78d7a41a9a8fe6d87a5e59500e51' }
it 'is prevented' do
expect(subject.status).to be(false)
expect(subject.message).to include('cannot be updated')
expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError, /cannot be updated/)
end
end
end
......@@ -81,15 +77,14 @@ describe Gitlab::Checks::ChangeAccess, lib: true do
let(:ref) { 'refs/tags/v9.1.0' }
it 'prevents creation below access level' do
expect(subject.status).to be(false)
expect(subject.message).to include('allowed to create this tag as it is protected')
expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError, /allowed to create this tag as it is protected/)
end
context 'when user has access' do
let!(:protected_tag) { create(:protected_tag, :developers_can_create, project: project, name: 'v*') }
it 'allows tag creation' do
expect(subject.status).to be(true)
expect { subject }.not_to raise_error
end
end
end
......@@ -101,9 +96,8 @@ describe Gitlab::Checks::ChangeAccess, lib: true do
let(:newrev) { '0000000000000000000000000000000000000000' }
let(:ref) { 'refs/heads/master' }
it 'returns an error' do
expect(subject.status).to be(false)
expect(subject.message).to eq('The default branch of a project cannot be deleted.')
it 'raises an error' do
expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'The default branch of a project cannot be deleted.')
end
end
......@@ -113,27 +107,24 @@ describe Gitlab::Checks::ChangeAccess, lib: true do
allow(ProtectedBranch).to receive(:protected?).with(project, 'feature').and_return(true)
end
it 'returns an error if the user is not allowed to do forced pushes to protected branches' do
it 'raises an error if the user is not allowed to do forced pushes to protected branches' do
expect(Gitlab::Checks::ForcePush).to receive(:force_push?).and_return(true)
expect(subject.status).to be(false)
expect(subject.message).to eq('You are not allowed to force push code to a protected branch on this project.')
expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to force push code to a protected branch on this project.')
end
it 'returns an error if the user is not allowed to merge to protected branches' do
it 'raises an error if the user is not allowed to merge to protected branches' do
expect_any_instance_of(Gitlab::Checks::MatchingMergeRequest).to receive(:match?).and_return(true)
expect(user_access).to receive(:can_merge_to_branch?).and_return(false)
expect(user_access).to receive(:can_push_to_branch?).and_return(false)
expect(subject.status).to be(false)
expect(subject.message).to eq('You are not allowed to merge code into protected branches on this project.')
expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to merge code into protected branches on this project.')
end
it 'returns an error if the user is not allowed to push to protected branches' do
it 'raises an error if the user is not allowed to push to protected branches' do
expect(user_access).to receive(:can_push_to_branch?).and_return(false)
expect(subject.status).to be(false)
expect(subject.message).to eq('You are not allowed to push code to protected branches on this project.')
expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to push code to protected branches on this project.')
end
context 'branch deletion' do
......@@ -141,9 +132,8 @@ describe Gitlab::Checks::ChangeAccess, lib: true do
let(:ref) { 'refs/heads/feature' }
context 'if the user is not allowed to delete protected branches' do
it 'returns an error' do
expect(subject.status).to be(false)
expect(subject.message).to eq('You are not allowed to delete protected branches from this project. Only a project master or owner can delete a protected branch.')
it 'raises an error' do
expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to delete protected branches from this project. Only a project master or owner can delete a protected branch.')
end
end
......@@ -156,14 +146,13 @@ describe Gitlab::Checks::ChangeAccess, lib: true do
let(:protocol) { 'web' }
it 'allows branch deletion' do
expect(subject.status).to be(true)
expect { subject }.not_to raise_error
end
end
context 'over SSH or HTTP' do
it 'returns an error' do
expect(subject.status).to be(false)
expect(subject.message).to eq('You can only delete protected branches using the web interface.')
it 'raises an error' do
expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You can only delete protected branches using the web interface.')
end
end
end
......
require 'spec_helper'
describe Gitlab::CiAccess, lib: true do
let(:access) { Gitlab::CiAccess.new }
describe '#can_do_action?' do
context 'when action is :build_download_code' do
it { expect(access.can_do_action?(:build_download_code)).to be_truthy }
end
context 'when action is not :build_download_code' do
it { expect(access.can_do_action?(:download_code)).to be_falsey }
end
end
end
This diff is collapsed.
......@@ -20,7 +20,7 @@ describe Gitlab::GitAccessWiki, lib: true do
subject { access.check('git-receive-pack', changes) }
it { expect(subject.allowed?).to be_truthy }
it { expect { subject }.not_to raise_error }
end
def changes
......@@ -36,7 +36,7 @@ describe Gitlab::GitAccessWiki, lib: true do
context 'when wiki feature is enabled' do
it 'give access to download wiki code' do
expect(subject.allowed?).to be_truthy
expect { subject }.not_to raise_error
end
end
......@@ -44,8 +44,7 @@ describe Gitlab::GitAccessWiki, lib: true do
it 'does not give access to download wiki code' do
project.project_feature.update_attribute(:wiki_access_level, ProjectFeature::DISABLED)
expect(subject.allowed?).to be_falsey
expect(subject.message).to match(/You are not allowed to download code/)
expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to download code from this project.')
end
end
end
......
This diff is collapsed.
......@@ -759,8 +759,8 @@ describe 'Git LFS API and storage' do
context 'tries to push to own project' do
let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) }
it 'responds with 401' do
expect(response).to have_http_status(401)
it 'responds with 403 (not 404 because project is public)' do
expect(response).to have_http_status(403)
end
end
......@@ -769,8 +769,9 @@ describe 'Git LFS API and storage' do
let(:pipeline) { create(:ci_empty_pipeline, project: other_project) }
let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) }
it 'responds with 401' do
expect(response).to have_http_status(401)
# I'm not sure what this tests that is different from the previous test
it 'responds with 403 (not 404 because project is public)' do
expect(response).to have_http_status(403)
end
end
end
......@@ -778,8 +779,8 @@ describe 'Git LFS API and storage' do
context 'does not have user' do
let(:build) { create(:ci_build, :running, pipeline: pipeline) }
it 'responds with 401' do
expect(response).to have_http_status(401)
it 'responds with 403 (not 404 because project is public)' do
expect(response).to have_http_status(403)
end
end
end
......@@ -979,8 +980,8 @@ describe 'Git LFS API and storage' do
put_authorize
end
it 'responds with 401' do
expect(response).to have_http_status(401)
it 'responds with 403 (not 404 because the build user can read the project)' do
expect(response).to have_http_status(403)
end
end
......@@ -993,8 +994,8 @@ describe 'Git LFS API and storage' do
put_authorize
end
it 'responds with 401' do
expect(response).to have_http_status(401)
it 'responds with 404 (do not leak non-public project existence)' do
expect(response).to have_http_status(404)
end
end
end
......@@ -1006,8 +1007,8 @@ describe 'Git LFS API and storage' do
put_authorize
end
it 'responds with 401' do
expect(response).to have_http_status(401)
it 'responds with 404 (do not leak non-public project existence)' do
expect(response).to have_http_status(404)
end
end
end
......@@ -1079,8 +1080,8 @@ describe 'Git LFS API and storage' do
context 'tries to push to own project' do
let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) }
it 'responds with 401' do
expect(response).to have_http_status(401)
it 'responds with 403 (not 404 because project is public)' do
expect(response).to have_http_status(403)
end
end
......@@ -1089,8 +1090,9 @@ describe 'Git LFS API and storage' do
let(:pipeline) { create(:ci_empty_pipeline, project: other_project) }
let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) }
it 'responds with 401' do
expect(response).to have_http_status(401)
# I'm not sure what this tests that is different from the previous test
it 'responds with 403 (not 404 because project is public)' do
expect(response).to have_http_status(403)
end
end
end
......@@ -1098,8 +1100,8 @@ describe 'Git LFS API and storage' do
context 'does not have user' do
let(:build) { create(:ci_build, :running, pipeline: pipeline) }
it 'responds with 401' do
expect(response).to have_http_status(401)
it 'responds with 403 (not 404 because project is public)' do
expect(response).to have_http_status(403)
end
end
end
......
......@@ -35,9 +35,14 @@ module GitHttpHelpers
yield response
end
def download_or_upload(*args, &block)
download(*args, &block)
upload(*args, &block)
end
def auth_env(user, password, spnego_request_token)
env = workhorse_internal_api_request_header
if user && password
if user
env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(user, password)
elsif spnego_request_token
env['HTTP_AUTHORIZATION'] = "Negotiate #{::Base64.strict_encode64('opaque_request_token')}"
......@@ -45,4 +50,19 @@ module GitHttpHelpers
env
end
def git_access_error(error_key)
message = Gitlab::GitAccess::ERROR_MESSAGES[error_key]
message || raise("GitAccess error message key '#{error_key}' not found")
end
def git_access_wiki_error(error_key)
message = Gitlab::GitAccessWiki::ERROR_MESSAGES[error_key]
message || raise("GitAccessWiki error message key '#{error_key}' not found")
end
def change_access_error(error_key)
message = Gitlab::Checks::ChangeAccess::ERROR_MESSAGES[error_key]
message || raise("ChangeAccess error message key '#{error_key}' not found")
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