diff options
Diffstat (limited to 'lib/gitlab_shell.rb')
-rw-r--r-- | lib/gitlab_shell.rb | 54 |
1 files changed, 37 insertions, 17 deletions
diff --git a/lib/gitlab_shell.rb b/lib/gitlab_shell.rb index 9644cf4..74af62a 100644 --- a/lib/gitlab_shell.rb +++ b/lib/gitlab_shell.rb @@ -17,6 +17,7 @@ class GitlabShell # rubocop:disable Metrics/ClassLength }.freeze API_COMMANDS = %w(2fa_recovery_codes).freeze GL_PROTOCOL = 'ssh'.freeze + HTTP_SUCCESS_CODES = %w{200 201}.freeze attr_accessor :key_id, :gl_repository, :repo_name, :command, :git_access attr_reader :repo_path @@ -38,29 +39,29 @@ class GitlabShell # rubocop:disable Metrics/ClassLength args = Shellwords.shellwords(origin_cmd) args = parse_cmd(args) + access_result = nil if GIT_COMMANDS.include?(args.first) - GitlabMetrics.measure('verify-access') { verify_access } + GitlabMetrics.measure('verify-access') { access_result = verify_access } end - process_cmd(args) - - true + process_cmd(access_result, args) rescue GitlabNet::ApiUnreachableError $stderr.puts "GitLab: Failed to authorize your Git request: internal API unreachable" 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 CustomActionStatus::UnsuccessfulError + $stderr.puts "GitLab: A custom action error has occurred" + false end protected @@ -101,17 +102,13 @@ class GitlabShell # rubocop:disable Metrics/ClassLength end def verify_access - status = api.check_access(@git_access, nil, @repo_name, @key_id, '_any', GL_PROTOCOL) + result = api.check_access(@git_access, nil, @repo_name, @key_id, '_any', GL_PROTOCOL) + raise AccessDeniedError, result.message unless result.allowed? - raise AccessDeniedError, status.message unless status.allowed? - - self.repo_path = status.repository_path - @gl_repository = status.gl_repository - @gitaly = status.gitaly - @username = status.gl_username + result end - def process_cmd(args) + def process_cmd(access_result, args) return send("api_#{@command}") if API_COMMANDS.include?(@command) if @command == 'git-lfs-authenticate' @@ -119,9 +116,23 @@ class GitlabShell # rubocop:disable Metrics/ClassLength $logger.info('Processing LFS authentication', user: log_username) lfs_authenticate end - return + return true end + case access_result + when GitAccessStatus + exec_cmd_for_gitaly(access_result, args) + when CustomActionStatus + exec_custom_action(access_result) + end + end + + def exec_cmd_for_gitaly(access_result, args) + self.repo_path = access_result.repository_path + @gl_repository = access_result.gl_repository + @gitaly = access_result.gitaly + @username = access_result.gl_username + executable = @command args = [repo_path] @@ -147,6 +158,16 @@ class GitlabShell # rubocop:disable Metrics/ClassLength exec_cmd(executable, *args) end + def exec_custom_action(access_result) + resp = access_result.execute(@key_id) + + unless resp || HTTP_SUCCESS_CODES.include?(resp.code) + raise CustomActionStatus::UnsuccessfulError, resp.body + end + + true + end + # This method is not covered by Rspec because it ends the current Ruby process. def exec_cmd(*args) # If you want to call a command without arguments, use @@ -183,7 +204,7 @@ class GitlabShell # rubocop:disable Metrics/ClassLength end def api - GitlabNet.new + GitlabNet.new # TODO: Can this be memoised? end def user @@ -213,7 +234,6 @@ class GitlabShell # rubocop:disable Metrics/ClassLength def lfs_authenticate lfs_access = api.lfs_authenticate(@key_id, @repo_name) - return unless lfs_access puts lfs_access.authentication_payload |