diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-01-24 21:09:00 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-01-24 21:09:00 +0300 |
commit | 411cc77938f99b495e0fe802705d275a28e939ef (patch) | |
tree | 97770ec9904daeaaa1f7546b191d23b0a642da47 /app/controllers/repositories/git_http_client_controller.rb | |
parent | 3e36f70be4bd74a412b2ea1286090b54803a8c20 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/controllers/repositories/git_http_client_controller.rb')
-rw-r--r-- | app/controllers/repositories/git_http_client_controller.rb | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/app/controllers/repositories/git_http_client_controller.rb b/app/controllers/repositories/git_http_client_controller.rb new file mode 100644 index 00000000000..76eb7c67205 --- /dev/null +++ b/app/controllers/repositories/git_http_client_controller.rb @@ -0,0 +1,125 @@ +# frozen_string_literal: true + +module Repositories + class GitHttpClientController < Repositories::ApplicationController + include ActionController::HttpAuthentication::Basic + include KerberosSpnegoHelper + include Gitlab::Utils::StrongMemoize + + attr_reader :authentication_result, :redirected_path + + delegate :actor, :authentication_abilities, to: :authentication_result, allow_nil: true + delegate :type, to: :authentication_result, allow_nil: true, prefix: :auth_result + + alias_method :user, :actor + alias_method :authenticated_user, :actor + + # Git clients will not know what authenticity token to send along + skip_around_action :set_session_storage + skip_before_action :verify_authenticity_token + + before_action :parse_repo_path + before_action :authenticate_user + + private + + def download_request? + raise NotImplementedError + end + + def upload_request? + raise NotImplementedError + end + + def authenticate_user + @authentication_result = Gitlab::Auth::Result.new + + if allow_basic_auth? && basic_auth_provided? + login, password = user_name_and_password(request) + + if handle_basic_authentication(login, password) + return # Allow access + end + elsif allow_kerberos_spnego_auth? && spnego_provided? + kerberos_user = find_kerberos_user + + if kerberos_user + @authentication_result = Gitlab::Auth::Result.new( + kerberos_user, nil, :kerberos, Gitlab::Auth.full_authentication_abilities) + + send_final_spnego_response + return # Allow access + end + elsif http_download_allowed? + + @authentication_result = Gitlab::Auth::Result.new(nil, project, :none, [:download_code]) + + return # Allow access + end + + send_challenges + render plain: "HTTP Basic: Access denied\n", status: :unauthorized + rescue Gitlab::Auth::MissingPersonalAccessTokenError + render_missing_personal_access_token + end + + def basic_auth_provided? + has_basic_credentials?(request) + end + + def send_challenges + challenges = [] + challenges << 'Basic realm="GitLab"' if allow_basic_auth? + challenges << spnego_challenge if allow_kerberos_spnego_auth? + headers['Www-Authenticate'] = challenges.join("\n") if challenges.any? + end + + def project + parse_repo_path unless defined?(@project) + + @project + end + + def parse_repo_path + @project, @repo_type, @redirected_path = Gitlab::RepoPath.parse("#{params[:namespace_id]}/#{params[:repository_id]}") + end + + def render_missing_personal_access_token + render plain: "HTTP Basic: Access denied\n" \ + "You must use a personal access token with 'read_repository' or 'write_repository' scope for Git over HTTP.\n" \ + "You can generate one at #{profile_personal_access_tokens_url}", + status: :unauthorized + end + + def repository + strong_memoize(:repository) do + repo_type.repository_for(project) + end + end + + def repo_type + parse_repo_path unless defined?(@repo_type) + + @repo_type + end + + def handle_basic_authentication(login, password) + @authentication_result = Gitlab::Auth.find_for_git_client( + login, password, project: project, ip: request.ip) + + @authentication_result.success? + end + + def ci? + authentication_result.ci?(project) + end + + def http_download_allowed? + Gitlab::ProtocolAccess.allowed?('http') && + download_request? && + project && Guest.can?(:download_code, project) + end + end +end + +Repositories::GitHttpClientController.prepend_if_ee('EE::Repositories::GitHttpClientController') |