Commit 84d99ff3 authored by Ash McKenzie's avatar Ash McKenzie

Merge branch 'debian_unauthorized_triggers_auth' into 'master'

Fix Debian packages API to raise 401 Unauthorized instead of a 404 Not Found

See merge request gitlab-org/gitlab!51734
parents f05278b6 daf8d8f5
...@@ -92,12 +92,11 @@ module EE ...@@ -92,12 +92,11 @@ module EE
# admin users can only access project if they are direct member # admin users can only access project if they are direct member
ability = job_token_authentication? ? :build_read_project : :read_project ability = job_token_authentication? ? :build_read_project : :read_project
if can?(current_user, ability, project) return project if can?(current_user, ability, project)
project return unauthorized! if authenticate_non_public?
else
not_found!('Project') not_found!('Project')
end end
end
override :find_group! override :find_group!
def find_group!(id) def find_group!(id)
......
...@@ -8,6 +8,8 @@ module API ...@@ -8,6 +8,8 @@ module API
resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
before do before do
require_packages_enabled!
not_found! unless ::Feature.enabled?(:debian_packages, user_group) not_found! unless ::Feature.enabled?(:debian_packages, user_group)
authorize_read_package!(user_group) authorize_read_package!(user_group)
......
...@@ -56,7 +56,7 @@ module API ...@@ -56,7 +56,7 @@ module API
detail 'This feature was introduced in GitLab 13.5' detail 'This feature was introduced in GitLab 13.5'
end end
route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
get 'Release.gpg' do get 'Release.gpg' do
not_found! not_found!
end end
...@@ -66,7 +66,7 @@ module API ...@@ -66,7 +66,7 @@ module API
detail 'This feature was introduced in GitLab 13.5' detail 'This feature was introduced in GitLab 13.5'
end end
route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
get 'Release' do get 'Release' do
# https://gitlab.com/gitlab-org/gitlab/-/issues/5835#note_414103286 # https://gitlab.com/gitlab-org/gitlab/-/issues/5835#note_414103286
'TODO Release' 'TODO Release'
...@@ -77,7 +77,7 @@ module API ...@@ -77,7 +77,7 @@ module API
detail 'This feature was introduced in GitLab 13.5' detail 'This feature was introduced in GitLab 13.5'
end end
route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
get 'InRelease' do get 'InRelease' do
not_found! not_found!
end end
...@@ -93,7 +93,7 @@ module API ...@@ -93,7 +93,7 @@ module API
detail 'This feature was introduced in GitLab 13.5' detail 'This feature was introduced in GitLab 13.5'
end end
route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
get 'Packages' do get 'Packages' do
# https://gitlab.com/gitlab-org/gitlab/-/issues/5835#note_414103286 # https://gitlab.com/gitlab-org/gitlab/-/issues/5835#note_414103286
'TODO Packages' 'TODO Packages'
...@@ -116,7 +116,7 @@ module API ...@@ -116,7 +116,7 @@ module API
detail 'This feature was introduced in GitLab 13.5' detail 'This feature was introduced in GitLab 13.5'
end end
route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
get ':file_name', requirements: FILE_NAME_REQUIREMENTS do get ':file_name', requirements: FILE_NAME_REQUIREMENTS do
# https://gitlab.com/gitlab-org/gitlab/-/issues/5835#note_414103286 # https://gitlab.com/gitlab-org/gitlab/-/issues/5835#note_414103286
'TODO File' 'TODO File'
......
...@@ -8,6 +8,8 @@ module API ...@@ -8,6 +8,8 @@ module API
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
before do before do
require_packages_enabled!
not_found! unless ::Feature.enabled?(:debian_packages, user_project) not_found! unless ::Feature.enabled?(:debian_packages, user_project)
authorize_read_package! authorize_read_package!
...@@ -28,7 +30,7 @@ module API ...@@ -28,7 +30,7 @@ module API
requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)' requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)'
end end
route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
put do put do
authorize_upload!(authorized_user_project) authorize_upload!(authorized_user_project)
bad_request!('File is too large') if authorized_user_project.actual_limits.exceeded?(:debian_max_file_size, params[:file].size) bad_request!('File is too large') if authorized_user_project.actual_limits.exceeded?(:debian_max_file_size, params[:file].size)
...@@ -43,7 +45,7 @@ module API ...@@ -43,7 +45,7 @@ module API
end end
# PUT {projects|groups}/:id/packages/debian/:file_name/authorize # PUT {projects|groups}/:id/packages/debian/:file_name/authorize
route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true
put 'authorize' do put 'authorize' do
authorize_workhorse!( authorize_workhorse!(
subject: authorized_user_project, subject: authorized_user_project,
......
...@@ -30,20 +30,6 @@ module API ...@@ -30,20 +30,6 @@ module API
str.gsub(/![[:alpha:]]/) { |s| s[1..].upcase } str.gsub(/![[:alpha:]]/) { |s| s[1..].upcase }
end end
def find_project!(id)
# based on API::Helpers::Packages::BasicAuthHelpers#authorized_project_find!
project = find_project(id)
return project if project && can?(current_user, :read_project, project)
if current_user
not_found!('Project')
else
unauthorized!
end
end
def find_module def find_module
not_found! unless Feature.enabled?(:go_proxy, user_project) not_found! unless Feature.enabled?(:go_proxy, user_project)
...@@ -74,7 +60,7 @@ module API ...@@ -74,7 +60,7 @@ module API
requires :id, type: String, desc: 'The ID of a project' requires :id, type: String, desc: 'The ID of a project'
requires :module_name, type: String, desc: 'Module name', coerce_with: ->(val) { CGI.unescape(val) } requires :module_name, type: String, desc: 'Module name', coerce_with: ->(val) { CGI.unescape(val) }
end end
route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true, authenticate_non_public: true
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
before do before do
authorize_read_package! authorize_read_package!
......
...@@ -119,12 +119,11 @@ module API ...@@ -119,12 +119,11 @@ module API
def find_project!(id) def find_project!(id)
project = find_project(id) project = find_project(id)
if can?(current_user, :read_project, project) return project if can?(current_user, :read_project, project)
project return unauthorized! if authenticate_non_public?
else
not_found!('Project') not_found!('Project')
end end
end
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
def find_group(id) def find_group(id)
...@@ -139,12 +138,11 @@ module API ...@@ -139,12 +138,11 @@ module API
def find_group!(id) def find_group!(id)
group = find_group(id) group = find_group(id)
if can?(current_user, :read_group, group) return group if can?(current_user, :read_group, group)
group return unauthorized! if authenticate_non_public?
else
not_found!('Group') not_found!('Group')
end end
end
def check_namespace_access(namespace) def check_namespace_access(namespace)
return namespace if can?(current_user, :read_namespace, namespace) return namespace if can?(current_user, :read_namespace, namespace)
...@@ -657,6 +655,10 @@ module API ...@@ -657,6 +655,10 @@ module API
Gitlab::Shell.secret_token Gitlab::Shell.secret_token
end end
def authenticate_non_public?
route_authentication_setting[:authenticate_non_public] && !current_user
end
def send_git_blob(repository, blob) def send_git_blob(repository, blob)
env['api.format'] = :txt env['api.format'] = :txt
content_type 'text/plain' content_type 'text/plain'
......
...@@ -201,7 +201,7 @@ RSpec.shared_examples 'rejects Debian access with unknown project id' do ...@@ -201,7 +201,7 @@ RSpec.shared_examples 'rejects Debian access with unknown project id' do
let(:project) { double(id: non_existing_record_id) } let(:project) { double(id: non_existing_record_id) }
context 'as anonymous' do context 'as anonymous' do
it_behaves_like 'Debian project repository GET request', :anonymous, true, :not_found, nil it_behaves_like 'Debian project repository GET request', :anonymous, true, :unauthorized, nil
end end
context 'as authenticated user' do context 'as authenticated user' do
...@@ -228,13 +228,13 @@ RSpec.shared_examples 'Debian project repository GET endpoint' do |success_statu ...@@ -228,13 +228,13 @@ RSpec.shared_examples 'Debian project repository GET endpoint' do |success_statu
'PUBLIC' | :anonymous | false | true | success_status | success_body 'PUBLIC' | :anonymous | false | true | success_status | success_body
'PRIVATE' | :developer | true | true | success_status | success_body 'PRIVATE' | :developer | true | true | success_status | success_body
'PRIVATE' | :guest | true | true | :forbidden | nil 'PRIVATE' | :guest | true | true | :forbidden | nil
'PRIVATE' | :developer | true | false | :not_found | nil 'PRIVATE' | :developer | true | false | :unauthorized | nil
'PRIVATE' | :guest | true | false | :not_found | nil 'PRIVATE' | :guest | true | false | :unauthorized | nil
'PRIVATE' | :developer | false | true | :not_found | nil 'PRIVATE' | :developer | false | true | :not_found | nil
'PRIVATE' | :guest | false | true | :not_found | nil 'PRIVATE' | :guest | false | true | :not_found | nil
'PRIVATE' | :developer | false | false | :not_found | nil 'PRIVATE' | :developer | false | false | :unauthorized | nil
'PRIVATE' | :guest | false | false | :not_found | nil 'PRIVATE' | :guest | false | false | :unauthorized | nil
'PRIVATE' | :anonymous | false | true | :not_found | nil 'PRIVATE' | :anonymous | false | true | :unauthorized | nil
end end
with_them do with_them do
...@@ -263,13 +263,13 @@ RSpec.shared_examples 'Debian project repository PUT endpoint' do |success_statu ...@@ -263,13 +263,13 @@ RSpec.shared_examples 'Debian project repository PUT endpoint' do |success_statu
'PUBLIC' | :anonymous | false | true | :unauthorized | nil 'PUBLIC' | :anonymous | false | true | :unauthorized | nil
'PRIVATE' | :developer | true | true | success_status | nil 'PRIVATE' | :developer | true | true | success_status | nil
'PRIVATE' | :guest | true | true | :forbidden | nil 'PRIVATE' | :guest | true | true | :forbidden | nil
'PRIVATE' | :developer | true | false | :not_found | nil 'PRIVATE' | :developer | true | false | :unauthorized | nil
'PRIVATE' | :guest | true | false | :not_found | nil 'PRIVATE' | :guest | true | false | :unauthorized | nil
'PRIVATE' | :developer | false | true | :not_found | nil 'PRIVATE' | :developer | false | true | :not_found | nil
'PRIVATE' | :guest | false | true | :not_found | nil 'PRIVATE' | :guest | false | true | :not_found | nil
'PRIVATE' | :developer | false | false | :not_found | nil 'PRIVATE' | :developer | false | false | :unauthorized | nil
'PRIVATE' | :guest | false | false | :not_found | nil 'PRIVATE' | :guest | false | false | :unauthorized | nil
'PRIVATE' | :anonymous | false | true | :not_found | nil 'PRIVATE' | :anonymous | false | true | :unauthorized | nil
end end
with_them do with_them do
...@@ -321,7 +321,7 @@ RSpec.shared_examples 'rejects Debian access with unknown group id' do ...@@ -321,7 +321,7 @@ RSpec.shared_examples 'rejects Debian access with unknown group id' do
let(:group) { double(id: non_existing_record_id) } let(:group) { double(id: non_existing_record_id) }
context 'as anonymous' do context 'as anonymous' do
it_behaves_like 'Debian group repository GET request', :anonymous, true, :not_found, nil it_behaves_like 'Debian group repository GET request', :anonymous, true, :unauthorized, nil
end end
context 'as authenticated user' do context 'as authenticated user' do
...@@ -348,13 +348,13 @@ RSpec.shared_examples 'Debian group repository GET endpoint' do |success_status, ...@@ -348,13 +348,13 @@ RSpec.shared_examples 'Debian group repository GET endpoint' do |success_status,
'PUBLIC' | :anonymous | false | true | success_status | success_body 'PUBLIC' | :anonymous | false | true | success_status | success_body
'PRIVATE' | :developer | true | true | success_status | success_body 'PRIVATE' | :developer | true | true | success_status | success_body
'PRIVATE' | :guest | true | true | :forbidden | nil 'PRIVATE' | :guest | true | true | :forbidden | nil
'PRIVATE' | :developer | true | false | :not_found | nil 'PRIVATE' | :developer | true | false | :unauthorized | nil
'PRIVATE' | :guest | true | false | :not_found | nil 'PRIVATE' | :guest | true | false | :unauthorized | nil
'PRIVATE' | :developer | false | true | :not_found | nil 'PRIVATE' | :developer | false | true | :not_found | nil
'PRIVATE' | :guest | false | true | :not_found | nil 'PRIVATE' | :guest | false | true | :not_found | nil
'PRIVATE' | :developer | false | false | :not_found | nil 'PRIVATE' | :developer | false | false | :unauthorized | nil
'PRIVATE' | :guest | false | false | :not_found | nil 'PRIVATE' | :guest | false | false | :unauthorized | nil
'PRIVATE' | :anonymous | false | true | :not_found | nil 'PRIVATE' | :anonymous | false | true | :unauthorized | nil
end end
with_them do with_them 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