diff options
Diffstat (limited to 'lib/gitlab_shell.rb')
-rw-r--r-- | lib/gitlab_shell.rb | 55 |
1 files changed, 38 insertions, 17 deletions
diff --git a/lib/gitlab_shell.rb b/lib/gitlab_shell.rb index 4d0b26f..79af861 100644 --- a/lib/gitlab_shell.rb +++ b/lib/gitlab_shell.rb @@ -5,16 +5,22 @@ require 'pathname' require_relative 'gitlab_net' require_relative 'gitlab_metrics' +require_relative 'action' class GitlabShell # rubocop:disable Metrics/ClassLength class AccessDeniedError < StandardError; end class DisallowedCommandError < StandardError; end class InvalidRepositoryPathError < StandardError; end + GIT_UPLOAD_PACK_COMMAND = 'git-upload-pack' + GIT_RECEIVE_PACK_COMMAND = 'git-receive-pack' + GIT_UPLOAD_ARCHIVE_COMMAND = 'git-upload-archive' + GIT_LFS_AUTHENTICATE_COMMAND = 'git-lfs-authenticate' + GITALY_COMMANDS = { - 'git-upload-pack' => File.join(ROOT_PATH, 'bin', 'gitaly-upload-pack'), - 'git-upload-archive' => File.join(ROOT_PATH, 'bin', 'gitaly-upload-archive'), - 'git-receive-pack' => File.join(ROOT_PATH, 'bin', 'gitaly-receive-pack') + GIT_UPLOAD_PACK_COMMAND => File.join(ROOT_PATH, 'bin', 'gitaly-upload-pack'), + GIT_UPLOAD_ARCHIVE_COMMAND => File.join(ROOT_PATH, 'bin', 'gitaly-upload-archive'), + GIT_RECEIVE_PACK_COMMAND => File.join(ROOT_PATH, 'bin', 'gitaly-receive-pack') }.freeze GIT_COMMANDS = (GITALY_COMMANDS.keys + ['git-lfs-authenticate']).freeze @@ -45,8 +51,17 @@ class GitlabShell # rubocop:disable Metrics/ClassLength args = Shellwords.shellwords(origin_cmd) args = parse_cmd(args) + access_status = nil + if GIT_COMMANDS.include?(args.first) - GitlabMetrics.measure('verify-access') { verify_access } + access_status = GitlabMetrics.measure('verify-access') { verify_access } + + @gl_repository = access_status.gl_repository + @git_protocol = ENV['GIT_PROTOCOL'] + @gitaly = access_status.gitaly + @username = access_status.gl_username + @git_config_options = access_status.git_config_options + @gl_id = access_status.gl_id if defined?(@who) elsif !defined?(@gl_id) # We're processing an API command like 2fa_recovery_codes, but # don't have a @gl_id yet, that means we're in the "username" @@ -55,6 +70,13 @@ class GitlabShell # rubocop:disable Metrics/ClassLength user end + if @command == GIT_RECEIVE_PACK_COMMAND && access_status.custom_action? + # If the response from /api/v4/allowed is a HTTP 300, we need to perform + # a Custom Action and therefore should return and not call process_cmd() + # + return process_custom_action(access_status) + end + process_cmd(args) true @@ -63,17 +85,19 @@ class GitlabShell # rubocop:disable Metrics/ClassLength false rescue AccessDeniedError => ex $logger.warn('Access denied', command: origin_cmd, user: log_username) - $stderr.puts "GitLab: #{ex.message}" false rescue DisallowedCommandError $logger.warn('Denied disallowed command', command: origin_cmd, user: log_username) - $stderr.puts "GitLab: Disallowed command" false rescue InvalidRepositoryPathError $stderr.puts "GitLab: Invalid repository path" false + rescue Action::Custom::BaseError => ex + $logger.warn('Custom action error', command: origin_cmd, user: log_username) + $stderr.puts "GitLab: #{ex.message}" + false end protected @@ -94,14 +118,14 @@ class GitlabShell # rubocop:disable Metrics/ClassLength raise DisallowedCommandError unless GIT_COMMANDS.include?(@command) case @command - when 'git-lfs-authenticate' + when GIT_LFS_AUTHENTICATE_COMMAND raise DisallowedCommandError unless args.count >= 2 @repo_name = args[1] case args[2] when 'download' - @git_access = 'git-upload-pack' + @git_access = GIT_UPLOAD_PACK_COMMAND when 'upload' - @git_access = 'git-receive-pack' + @git_access = GIT_RECEIVE_PACK_COMMAND else raise DisallowedCommandError end @@ -118,14 +142,11 @@ class GitlabShell # rubocop:disable Metrics/ClassLength raise AccessDeniedError, status.message unless status.allowed? - @gl_repository = status.gl_repository - @git_protocol = ENV['GIT_PROTOCOL'] - @gitaly = status.gitaly - @username = status.gl_username - @git_config_options = status.git_config_options - if defined?(@who) - @gl_id = status.gl_id - end + status + end + + def process_custom_action(access_status) + Action::Custom.new(@gl_id, access_status.payload).execute end def process_cmd(args) |