Commit e1d4b86c authored by Kamil Trzcinski's avatar Kamil Trzcinski

Introduce build_read_project and perform license check

parent 4bc75dc9
...@@ -6,6 +6,7 @@ class License < ActiveRecord::Base ...@@ -6,6 +6,7 @@ class License < ActiveRecord::Base
AUDITOR_USER_FEATURE = 'GitLab_Auditor_User'.freeze AUDITOR_USER_FEATURE = 'GitLab_Auditor_User'.freeze
BURNDOWN_CHARTS_FEATURE = 'GitLab_BurndownCharts'.freeze BURNDOWN_CHARTS_FEATURE = 'GitLab_BurndownCharts'.freeze
CONTRIBUTION_ANALYTICS_FEATURE = 'GitLab_ContributionAnalytics'.freeze CONTRIBUTION_ANALYTICS_FEATURE = 'GitLab_ContributionAnalytics'.freeze
CROSS_PROJECT_PIPELINES_FEATURE = 'GitLab_CrossProjectPipelines'.freeze
DB_LOAD_BALANCING_FEATURE = 'GitLab_DbLoadBalancing'.freeze DB_LOAD_BALANCING_FEATURE = 'GitLab_DbLoadBalancing'.freeze
DEPLOY_BOARD_FEATURE = 'GitLab_DeployBoard'.freeze DEPLOY_BOARD_FEATURE = 'GitLab_DeployBoard'.freeze
ELASTIC_SEARCH_FEATURE = 'GitLab_ElasticSearch'.freeze ELASTIC_SEARCH_FEATURE = 'GitLab_ElasticSearch'.freeze
...@@ -51,6 +52,7 @@ class License < ActiveRecord::Base ...@@ -51,6 +52,7 @@ class License < ActiveRecord::Base
audit_events: AUDIT_EVENTS_FEATURE, audit_events: AUDIT_EVENTS_FEATURE,
burndown_charts: BURNDOWN_CHARTS_FEATURE, burndown_charts: BURNDOWN_CHARTS_FEATURE,
contribution_analytics: CONTRIBUTION_ANALYTICS_FEATURE, contribution_analytics: CONTRIBUTION_ANALYTICS_FEATURE,
cross_project_pipelines: CROSS_PROJECT_PIPELINES_FEATURE,
deploy_board: DEPLOY_BOARD_FEATURE, deploy_board: DEPLOY_BOARD_FEATURE,
export_issues: EXPORT_ISSUES_FEATURE, export_issues: EXPORT_ISSUES_FEATURE,
fast_forward_merge: FAST_FORWARD_MERGE_FEATURE, fast_forward_merge: FAST_FORWARD_MERGE_FEATURE,
...@@ -106,6 +108,7 @@ class License < ActiveRecord::Base ...@@ -106,6 +108,7 @@ class License < ActiveRecord::Base
*EES_FEATURES, *EES_FEATURES,
{ ADMIN_AUDIT_LOG_FEATURE => 1 }, { ADMIN_AUDIT_LOG_FEATURE => 1 },
{ AUDITOR_USER_FEATURE => 1 }, { AUDITOR_USER_FEATURE => 1 },
{ CROSS_PROJECT_PIPELINES_FEATURE => 1 },
{ DB_LOAD_BALANCING_FEATURE => 1 }, { DB_LOAD_BALANCING_FEATURE => 1 },
{ DEPLOY_BOARD_FEATURE => 1 }, { DEPLOY_BOARD_FEATURE => 1 },
{ FILE_LOCKS_FEATURE => 1 }, { FILE_LOCKS_FEATURE => 1 },
...@@ -131,6 +134,7 @@ class License < ActiveRecord::Base ...@@ -131,6 +134,7 @@ class License < ActiveRecord::Base
{ AUDITOR_USER_FEATURE => 1 }, { AUDITOR_USER_FEATURE => 1 },
{ BURNDOWN_CHARTS_FEATURE => 1 }, { BURNDOWN_CHARTS_FEATURE => 1 },
{ CONTRIBUTION_ANALYTICS_FEATURE => 1 }, { CONTRIBUTION_ANALYTICS_FEATURE => 1 },
{ CROSS_PROJECT_PIPELINES_FEATURE => 1 },
{ DEPLOY_BOARD_FEATURE => 1 }, { DEPLOY_BOARD_FEATURE => 1 },
{ EXPORT_ISSUES_FEATURE => 1 }, { EXPORT_ISSUES_FEATURE => 1 },
{ FAST_FORWARD_MERGE_FEATURE => 1 }, { FAST_FORWARD_MERGE_FEATURE => 1 },
......
...@@ -101,6 +101,7 @@ class ProjectPolicy < BasePolicy ...@@ -101,6 +101,7 @@ class ProjectPolicy < BasePolicy
end end
rule { owner | reporter }.policy do rule { owner | reporter }.policy do
enable :build_read_project
enable :build_download_code enable :build_download_code
enable :build_read_container_image enable :build_read_container_image
end end
......
--- ---
title: Allow artifacts access with CI_JOB_TOKEN title: Allow artifacts access with job_token parameter or CI_JOB_TOKEN header
merge_request: merge_request:
author: author:
...@@ -8,8 +8,8 @@ module API ...@@ -8,8 +8,8 @@ module API
PRIVATE_TOKEN_HEADER = "HTTP_PRIVATE_TOKEN".freeze PRIVATE_TOKEN_HEADER = "HTTP_PRIVATE_TOKEN".freeze
PRIVATE_TOKEN_PARAM = :private_token PRIVATE_TOKEN_PARAM = :private_token
CI_JOB_TOKEN_HEADER = "HTTP_JOB_TOKEN".freeze JOB_TOKEN_HEADER = "HTTP_JOB_TOKEN".freeze
CI_JOB_TOKEN_PARAM = :job_token JOB_TOKEN_PARAM = :job_token
included do |base| included do |base|
# OAuth2 Resource Server Authentication # OAuth2 Resource Server Authentication
...@@ -89,13 +89,14 @@ module API ...@@ -89,13 +89,14 @@ module API
find_user_by_authentication_token(token_string) || find_user_by_personal_access_token(token_string, scopes) find_user_by_authentication_token(token_string) || find_user_by_personal_access_token(token_string, scopes)
end end
def find_user_by_ci_token def find_user_by_job_token
return nil unless route_authentication_setting[:job_token_allowed] return @user_by_job_token if defined?(@user_by_job_token)
token_string = (params[CI_JOB_TOKEN_PARAM] || env[CI_JOB_TOKEN_HEADER]).to_s @user_by_job_token =
return nil unless token_string.present? if route_authentication_setting[:job_token_allowed]
token_string = params[JOB_TOKEN_PARAM].presence || env[JOB_TOKEN_HEADER].presence
Ci::Build.find_by_token(token_string)&.user Ci::Build.find_by_token(token_string)&.user if token_string
end
end end
def current_user def current_user
......
...@@ -58,9 +58,12 @@ module API ...@@ -58,9 +58,12 @@ module API
def find_project!(id) def find_project!(id)
project = find_project(id) project = find_project(id)
if ci_job_token && !current_user.authorized_projects.exists?(project) # CI job token authentication:
not_found!('Project') # this method grants limited privileged for admin users
elsif can?(current_user, :read_project, project) # admin users can only access project if they are direct member
ability = job_token_authentication? ? :build_read_project : :read_project
if can?(current_user, ability, project)
project project
else else
not_found!('Project') not_found!('Project')
...@@ -84,11 +87,13 @@ module API ...@@ -84,11 +87,13 @@ module API
end end
def find_group!(id) def find_group!(id)
# CI job token authentication:
# currently we do not allow any group access for CI job token
not_found!('Group') if job_token_authentication?
group = find_group(id) group = find_group(id)
if ci_job_token if can?(current_user, ability, group)
not_found!('Group')
elsif can?(current_user, :read_group, group)
group group
else else
not_found!('Group') not_found!('Group')
...@@ -352,10 +357,9 @@ module API ...@@ -352,10 +357,9 @@ module API
def private_token def private_token
params[APIGuard::PRIVATE_TOKEN_PARAM] || env[APIGuard::PRIVATE_TOKEN_HEADER] params[APIGuard::PRIVATE_TOKEN_PARAM] || env[APIGuard::PRIVATE_TOKEN_HEADER]
end
def ci_job_token def job_token_authentication?
params[APIGuard::CI_JOB_TOKEN_PARAM] || env[APIGuard::CI_JOB_TOKEN_HEADER] initial_current_user && initial_current_user == find_user_by_job_token
end end
def warden def warden
...@@ -372,12 +376,11 @@ module API ...@@ -372,12 +376,11 @@ module API
def initial_current_user def initial_current_user
return @initial_current_user if defined?(@initial_current_user) return @initial_current_user if defined?(@initial_current_user)
Gitlab::Auth::UniqueIpsLimiter.limit_user! do Gitlab::Auth::UniqueIpsLimiter.limit_user! do
@initial_current_user ||= find_user_by_private_token(scopes: scopes_registered_for_endpoint) @initial_current_user ||= find_user_by_private_token(scopes: scopes_registered_for_endpoint)
@initial_current_user ||= doorkeeper_guard(scopes: scopes_registered_for_endpoint) @initial_current_user ||= doorkeeper_guard(scopes: scopes_registered_for_endpoint)
@initial_current_user ||= find_user_from_warden @initial_current_user ||= find_user_from_warden
@initial_current_user ||= find_user_by_ci_token @initial_current_user ||= find_user_by_job_token
unless @initial_current_user && Gitlab::UserAccess.new(@initial_current_user).allowed? unless @initial_current_user && Gitlab::UserAccess.new(@initial_current_user).allowed?
@initial_current_user = nil @initial_current_user = nil
......
...@@ -80,6 +80,7 @@ module API ...@@ -80,6 +80,7 @@ module API
route_setting :authentication, job_token_allowed: true route_setting :authentication, job_token_allowed: true
get ':id/jobs/:job_id/artifacts' do get ':id/jobs/:job_id/artifacts' do
authorize_read_builds! authorize_read_builds!
check_cross_project_pipelines_feature!
build = get_build!(params[:job_id]) build = get_build!(params[:job_id])
...@@ -97,6 +98,7 @@ module API ...@@ -97,6 +98,7 @@ module API
get ':id/jobs/artifacts/:ref_name/download', get ':id/jobs/artifacts/:ref_name/download',
requirements: { ref_name: /.+/ } do requirements: { ref_name: /.+/ } do
authorize_read_builds! authorize_read_builds!
check_cross_project_pipelines_feature!
builds = user_project.latest_successful_builds_for(params[:ref_name]) builds = user_project.latest_successful_builds_for(params[:ref_name])
latest_build = builds.find_by!(name: params[:job]) latest_build = builds.find_by!(name: params[:job])
...@@ -244,6 +246,10 @@ module API ...@@ -244,6 +246,10 @@ module API
def authorize_update_builds! def authorize_update_builds!
authorize! :update_build, user_project authorize! :update_build, user_project
end end
def check_cross_project_pipelines_feature!
not_found!('Project') if job_token_authentication? && project.feature_available?(:cross_project_pipelines)
end
end end
end 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