summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/controllers/jwt_controller.rb26
-rw-r--r--app/controllers/projects/git_http_client_controller.rb8
-rw-r--r--app/controllers/projects/git_http_controller.rb2
-rw-r--r--app/helpers/lfs_helper.rb16
-rw-r--r--app/models/ci/build.rb13
-rw-r--r--app/models/project.rb6
-rw-r--r--app/policies/project_policy.rb17
-rw-r--r--app/services/auth/container_registry_authentication_service.rb34
8 files changed, 79 insertions, 43 deletions
diff --git a/app/controllers/jwt_controller.rb b/app/controllers/jwt_controller.rb
index 66ebdcc37a7..ed5d28e0d2c 100644
--- a/app/controllers/jwt_controller.rb
+++ b/app/controllers/jwt_controller.rb
@@ -11,7 +11,10 @@ class JwtController < ApplicationController
service = SERVICES[params[:service]]
return head :not_found unless service
- result = service.new(@project, @user, auth_params).execute
+ @@authentication_result ||= Gitlab::Auth.Result.new
+
+ result = service.new(@authentication_result.project, @authentication_result.user, auth_params).
+ execute(capabilities: @authentication_result.capabilities || [])
render json: result, status: result[:http_status]
end
@@ -20,30 +23,13 @@ class JwtController < ApplicationController
def authenticate_project_or_user
authenticate_with_http_basic do |login, password|
- # if it's possible we first try to authenticate project with login and password
- @project = authenticate_project(login, password)
- return if @project
-
- @user = authenticate_user(login, password)
- return if @user
+ @authentication_result = Gitlab::Auth.find_for_git_client(login, password, ip: request.ip)
- render_403
+ render_403 unless @authentication_result.succeeded?
end
end
def auth_params
params.permit(:service, :scope, :account, :client_id)
end
-
- def authenticate_project(login, password)
- if login == 'gitlab-ci-token'
- Project.with_builds_enabled.find_by(runners_token: password)
- end
- end
-
- def authenticate_user(login, password)
- user = Gitlab::Auth.find_with_user_password(login, password)
- Gitlab::Auth.rate_limit!(request.ip, success: user.present?, login: login)
- user
- end
end
diff --git a/app/controllers/projects/git_http_client_controller.rb b/app/controllers/projects/git_http_client_controller.rb
index f5ce63fdfed..6870102c296 100644
--- a/app/controllers/projects/git_http_client_controller.rb
+++ b/app/controllers/projects/git_http_client_controller.rb
@@ -4,7 +4,7 @@ class Projects::GitHttpClientController < Projects::ApplicationController
include ActionController::HttpAuthentication::Basic
include KerberosSpnegoHelper
- attr_reader :user
+ attr_reader :user, :capabilities
# Git clients will not know what authenticity token to send along
skip_before_action :verify_authenticity_token
@@ -34,6 +34,8 @@ class Projects::GitHttpClientController < Projects::ApplicationController
@user = auth_result.user
end
+ @capabilities = auth_result.capabilities || []
+
if ci? || user
return # Allow access
end
@@ -118,6 +120,10 @@ class Projects::GitHttpClientController < Projects::ApplicationController
@ci.present?
end
+ def has_capability?(capability)
+ @capabilities.include?(capability)
+ end
+
def verify_workhorse_api!
Gitlab::Workhorse.verify_api_request!(request.headers)
end
diff --git a/app/controllers/projects/git_http_controller.rb b/app/controllers/projects/git_http_controller.rb
index 9805705c4e3..89afaaed510 100644
--- a/app/controllers/projects/git_http_controller.rb
+++ b/app/controllers/projects/git_http_controller.rb
@@ -86,7 +86,7 @@ class Projects::GitHttpController < Projects::GitHttpClientController
end
def access
- @access ||= Gitlab::GitAccess.new(user, project, 'http')
+ @access ||= Gitlab::GitAccess.new(user, project, 'http', capabilities: capabilities)
end
def access_check
diff --git a/app/helpers/lfs_helper.rb b/app/helpers/lfs_helper.rb
index 5d82abfca79..a2359d94443 100644
--- a/app/helpers/lfs_helper.rb
+++ b/app/helpers/lfs_helper.rb
@@ -25,13 +25,25 @@ module LfsHelper
def lfs_download_access?
return false unless project.lfs_enabled?
- project.public? || ci? || (user && user.can?(:download_code, project))
+ project.public? || ci? || user_can_download_code? || build_can_download_code?
+ end
+
+ def user_can_download_code?
+ has_capability?(:download_code) && user && user.can?(:download_code, project)
+ end
+
+ def build_can_download_code?
+ has_capability?(:build_download_code) && user && user.can?(:build_download_code, project)
end
def lfs_upload_access?
return false unless project.lfs_enabled?
- user && user.can?(:push_code, project)
+ privileged_user_can_push_code?
+ end
+
+ def privileged_user_can_push_code?
+ has_capability?(:push_code) && user && user.can?(:push_code, project)
end
def render_lfs_forbidden
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index fb16bc06d71..29788b8285d 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -1,5 +1,7 @@
module Ci
class Build < CommitStatus
+ include TokenAuthenticatable
+
belongs_to :runner, class_name: 'Ci::Runner'
belongs_to :trigger_request, class_name: 'Ci::TriggerRequest'
belongs_to :erased_by, class_name: 'User'
@@ -23,7 +25,10 @@ module Ci
acts_as_taggable
+ add_authentication_token_field :token
+
before_save :update_artifacts_size, if: :artifacts_file_changed?
+ before_save :ensure_token
before_destroy { project }
after_create :execute_hooks
@@ -173,7 +178,7 @@ module Ci
end
def repo_url
- auth = "gitlab-ci-token:#{token}@"
+ auth = "gitlab-ci-token:#{ensure_token}@"
project.http_url_to_repo.sub(/^https?:\/\//) do |prefix|
prefix + auth
end
@@ -341,12 +346,8 @@ module Ci
)
end
- def token
- project.runners_token
- end
-
def valid_token?(token)
- project.valid_runners_token?(token)
+ self.token && ActiveSupport::SecurityUtils.variable_size_secure_compare(token, self.token)
end
def has_tags?
diff --git a/app/models/project.rb b/app/models/project.rb
index f3f3ffbbd28..16ca2b688c8 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -1138,12 +1138,6 @@ class Project < ActiveRecord::Base
self.runners_token && ActiveSupport::SecurityUtils.variable_size_secure_compare(token, self.runners_token)
end
- # TODO (ayufan): For now we use runners_token (backward compatibility)
- # In 8.4 every build will have its own individual token valid for time of build
- def valid_build_token?(token)
- self.builds_enabled? && self.runners_token && ActiveSupport::SecurityUtils.variable_size_secure_compare(token, self.runners_token)
- end
-
def build_coverage_enabled?
build_coverage_regex.present?
end
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index acf36d422d1..ce686af2ade 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -64,6 +64,12 @@ class ProjectPolicy < BasePolicy
can! :read_deployment
end
+ # Permissions given when an user is direct member of a group
+ def team_member_reporter_access!
+ can! :build_download_code
+ can! :build_read_container_image
+ end
+
def developer_access!
can! :admin_merge_request
can! :update_merge_request
@@ -109,6 +115,8 @@ class ProjectPolicy < BasePolicy
can! :read_commit_status
can! :read_pipeline
can! :read_container_image
+ can! :build_download_code
+ can! :build_read_container_image
end
def owner_access!
@@ -130,10 +138,11 @@ class ProjectPolicy < BasePolicy
def team_access!(user)
access = project.team.max_member_access(user.id)
- guest_access! if access >= Gitlab::Access::GUEST
- reporter_access! if access >= Gitlab::Access::REPORTER
- developer_access! if access >= Gitlab::Access::DEVELOPER
- master_access! if access >= Gitlab::Access::MASTER
+ guest_access! if access >= Gitlab::Access::GUEST
+ reporter_access! if access >= Gitlab::Access::REPORTER
+ team_member_reporter_access! if access >= Gitlab::Access::REPORTER
+ developer_access! if access >= Gitlab::Access::DEVELOPER
+ master_access! if access >= Gitlab::Access::MASTER
end
def archived_access!
diff --git a/app/services/auth/container_registry_authentication_service.rb b/app/services/auth/container_registry_authentication_service.rb
index 6072123b851..ba0b60abfe4 100644
--- a/app/services/auth/container_registry_authentication_service.rb
+++ b/app/services/auth/container_registry_authentication_service.rb
@@ -4,7 +4,9 @@ module Auth
AUDIENCE = 'container_registry'
- def execute
+ def execute(capabilities: capabilities)
+ @capabilities = capabilities
+
return error('not found', 404) unless registry.enabled
unless current_user || project
@@ -74,9 +76,9 @@ module Auth
case requested_action
when 'pull'
- requested_project == project || can?(current_user, :read_container_image, requested_project)
+ build_can_pull?(requested_project) || user_can_pull?(requested_project)
when 'push'
- requested_project == project || can?(current_user, :create_container_image, requested_project)
+ build_can_push?(requested_project) || user_can_push?(requested_project)
else
false
end
@@ -85,5 +87,31 @@ module Auth
def registry
Gitlab.config.registry
end
+
+ private
+
+ def build_can_pull?(requested_project)
+ # Build can:
+ # 1. pull from it's own project (for ex. a build)
+ # 2. read images from dependent projects if creator of build is a team member
+ @capabilities.include?(:build_read_container_image) &&
+ (requested_project == project || can?(current_user, :build_read_container_image, requested_project))
+ end
+
+ def user_can_pull?(requested_project)
+ @capabilities.include?(:read_container_image) &&
+ can?(current_user, :read_container_image, requested_project)
+ end
+
+ def build_can_push?(requested_project)
+ # Build can push only to project to from which he originates
+ @capabilities.include?(:build_create_container_image) &&
+ requested_project == project
+ end
+
+ def user_can_push?(requested_project)
+ @capabilities.include?(:create_container_image) &&
+ can?(current_user, :create_container_image, requested_project)
+ end
end
end