diff --git a/CHANGELOG b/CHANGELOG index 99f8c51218b1b0bbba37ee03d779da0b80ea55e9..6eab5fb9f1b32bb7dec881fce359d82522641fac 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,6 @@ v8.0.0 - SSH certificate support (!207) + - Support Git v2 protocol (!217) v7.2.0 - Update gitaly-proto to 0.109.0 (!216) diff --git a/lib/gitlab_access_status.rb b/lib/gitlab_access_status.rb index 44225aa4fe1d3da79e7d1fb4c923fc8c6a3318b5..c639462a0e8f151718c99537cbb435cc72805a39 100644 --- a/lib/gitlab_access_status.rb +++ b/lib/gitlab_access_status.rb @@ -1,9 +1,9 @@ require 'json' class GitAccessStatus - attr_reader :message, :gl_repository, :gl_id, :gl_username, :repository_path, :gitaly + attr_reader :message, :gl_repository, :gl_id, :gl_username, :repository_path, :gitaly, :git_protocol - def initialize(status, message, gl_repository:, gl_id:, gl_username:, repository_path:, gitaly:) + def initialize(status, message, gl_repository:, gl_id:, gl_username:, repository_path:, gitaly:, git_protocol:) @status = status @message = message @gl_repository = gl_repository @@ -11,6 +11,7 @@ class GitAccessStatus @gl_username = gl_username @repository_path = repository_path @gitaly = gitaly + @git_protocol = git_protocol end def self.create_from_json(json) @@ -21,7 +22,8 @@ class GitAccessStatus gl_id: values["gl_id"], gl_username: values["gl_username"], repository_path: values["repository_path"], - gitaly: values["gitaly"]) + gitaly: values["gitaly"], + git_protocol: values["git_protocol"]) end def allowed? diff --git a/lib/gitlab_net.rb b/lib/gitlab_net.rb index 7013d799c6a15f758b9f624acdfd3171f2570355..9cb7e5654838d6b57979f9159dec4c202fc7b8aa 100644 --- a/lib/gitlab_net.rb +++ b/lib/gitlab_net.rb @@ -44,7 +44,8 @@ class GitlabNet # rubocop:disable Metrics/ClassLength gl_id: nil, gl_username: nil, repository_path: nil, - gitaly: nil) + gitaly: nil, + git_protocol: nil) end end diff --git a/lib/gitlab_shell.rb b/lib/gitlab_shell.rb index 9f05004c0841ba4f306d2872b6bc2b35974771cc..78fdfe8524620dac9ed0a40133909cfab233ac4c 100644 --- a/lib/gitlab_shell.rb +++ b/lib/gitlab_shell.rb @@ -18,7 +18,7 @@ class GitlabShell # rubocop:disable Metrics/ClassLength API_COMMANDS = %w(2fa_recovery_codes).freeze GL_PROTOCOL = 'ssh'.freeze - attr_accessor :gl_id, :gl_repository, :repo_name, :command, :git_access + attr_accessor :gl_id, :gl_repository, :repo_name, :command, :git_access, :git_protocol attr_reader :repo_path def initialize(who) @@ -118,6 +118,7 @@ class GitlabShell # rubocop:disable Metrics/ClassLength self.repo_path = status.repository_path @gl_repository = status.gl_repository + @git_protocol = ENV['GIT_PROTOCOL'] @gitaly = status.gitaly @username = status.gl_username if defined?(@who) @@ -150,7 +151,8 @@ class GitlabShell # rubocop:disable Metrics/ClassLength 'repository' => @gitaly['repository'], 'gl_repository' => @gl_repository, 'gl_id' => @gl_id, - 'gl_username' => @username + 'gl_username' => @username, + 'git_protocol' => @git_protocol } args = [gitaly_address, JSON.dump(gitaly_request)] diff --git a/spec/gitlab_access_spec.rb b/spec/gitlab_access_spec.rb index d082176aa9f139b114322f0fc386e86ebda1f37e..f9717a7b13f063eae2919bce06929d892848fe46 100644 --- a/spec/gitlab_access_spec.rb +++ b/spec/gitlab_access_spec.rb @@ -3,8 +3,8 @@ require 'gitlab_access' describe GitlabAccess do let(:repository_path) { "/home/git/repositories" } - let(:repo_name) { 'dzaporozhets/gitlab-ci' } - let(:repo_path) { File.join(repository_path, repo_name) + ".git" } + let(:repo_name) { 'dzaporozhets/gitlab-ci' } + let(:repo_path) { File.join(repository_path, repo_name) + ".git" } let(:api) do double(GitlabNet).tap do |api| api.stub(check_access: GitAccessStatus.new(true, @@ -13,7 +13,8 @@ describe GitlabAccess do gl_id: 'user-123', gl_username: 'testuser', repository_path: '/home/git/repositories', - gitaly: nil)) + gitaly: nil, + git_protocol: 'version=2')) end end subject do @@ -35,14 +36,12 @@ describe GitlabAccess do describe "#exec" do context "access is granted" do - it "returns true" do expect(subject.exec).to be_truthy end end context "access is denied" do - before do api.stub(check_access: GitAccessStatus.new( false, @@ -51,7 +50,8 @@ describe GitlabAccess do gl_id: nil, gl_username: nil, repository_path: nil, - gitaly: nil + gitaly: nil, + git_protocol: nil )) end @@ -61,7 +61,6 @@ describe GitlabAccess do end context "API connection fails" do - before do api.stub(:check_access).and_raise(GitlabNet::ApiUnreachableError) end diff --git a/spec/gitlab_shell_spec.rb b/spec/gitlab_shell_spec.rb index 3f7c962c822b4345fb3b30d599844b19df1f58e5..382cad4e3cd0f88203bd2909729d40c83747b8ae 100644 --- a/spec/gitlab_shell_spec.rb +++ b/spec/gitlab_shell_spec.rb @@ -27,7 +27,8 @@ describe GitlabShell do gl_id: gl_id, gl_username: gl_username, repository_path: repo_path, - gitaly: { 'repository' => { 'relative_path' => repo_name, 'storage_name' => 'default'} , 'address' => 'unix:gitaly.socket' } + gitaly: { 'repository' => { 'relative_path' => repo_name, 'storage_name' => 'default'} , 'address' => 'unix:gitaly.socket' }, + git_protocol: git_protocol ) } @@ -41,11 +42,12 @@ describe GitlabShell do gl_id: gl_id, gl_username: gl_username, repository_path: repo_path, - gitaly: nil)) + gitaly: nil, + git_protocol: git_protocol)) api.stub(two_factor_recovery_codes: { - 'success' => true, - 'recovery_codes' => ['f67c514de60c4953', '41278385fc00c1e0'] - }) + 'success' => true, + 'recovery_codes' => %w[f67c514de60c4953 41278385fc00c1e0] + }) end end @@ -58,6 +60,7 @@ describe GitlabShell do let(:gl_repository) { 'project-1' } let(:gl_id) { 'user-1' } let(:gl_username) { 'testuser' } + let(:git_protocol) { 'version=2' } before do GitlabConfig.any_instance.stub(audit_usernames: false) @@ -72,7 +75,7 @@ describe GitlabShell do describe :parse_cmd do describe 'git' do context 'w/o namespace' do - let(:ssh_args) { %W(git-upload-pack gitlab-ci.git) } + let(:ssh_args) { %w(git-upload-pack gitlab-ci.git) } before do subject.send :parse_cmd, ssh_args @@ -84,7 +87,7 @@ describe GitlabShell do context 'namespace' do let(:repo_name) { 'dmitriy.zaporozhets/gitlab-ci.git' } - let(:ssh_args) { %W(git-upload-pack dmitriy.zaporozhets/gitlab-ci.git) } + let(:ssh_args) { %w(git-upload-pack dmitriy.zaporozhets/gitlab-ci.git) } before do subject.send :parse_cmd, ssh_args @@ -95,7 +98,7 @@ describe GitlabShell do end context 'with an invalid number of arguments' do - let(:ssh_args) { %W(foobar) } + let(:ssh_args) { %w(foobar) } it "should raise an DisallowedCommandError" do expect { subject.send :parse_cmd, ssh_args }.to raise_error(GitlabShell::DisallowedCommandError) @@ -123,7 +126,7 @@ describe GitlabShell do describe 'git-lfs' do let(:repo_name) { 'dzaporozhets/gitlab.git' } - let(:ssh_args) { %W(git-lfs-authenticate dzaporozhets/gitlab.git download) } + let(:ssh_args) { %w(git-lfs-authenticate dzaporozhets/gitlab.git download) } before do subject.send :parse_cmd, ssh_args @@ -136,7 +139,7 @@ describe GitlabShell do describe 'git-lfs old clients' do let(:repo_name) { 'dzaporozhets/gitlab.git' } - let(:ssh_args) { %W(git-lfs-authenticate dzaporozhets/gitlab.git download long_oid) } + let(:ssh_args) { %w(git-lfs-authenticate dzaporozhets/gitlab.git download long_oid) } before do subject.send :parse_cmd, ssh_args @@ -149,14 +152,26 @@ describe GitlabShell do end describe :exec do - let(:gitaly_message) { JSON.dump({ 'repository' => { 'relative_path' => repo_name, 'storage_name' => 'default' }, 'gl_repository' => gl_repository, 'gl_id' => gl_id, 'gl_username' => gl_username}) } + let(:gitaly_message) do + JSON.dump( + 'repository' => { 'relative_path' => repo_name, 'storage_name' => 'default' }, + 'gl_repository' => gl_repository, + 'gl_id' => gl_id, + 'gl_username' => gl_username, + 'git_protocol' => git_protocol + ) + end + + before do + allow(ENV).to receive(:[]).with('GIT_PROTOCOL').and_return(git_protocol) + end shared_examples_for 'upload-pack' do |command| let(:ssh_cmd) { "#{command} gitlab-ci.git" } after { subject.exec(ssh_cmd) } it "should process the command" do - subject.should_receive(:process_cmd).with(%W(git-upload-pack gitlab-ci.git)) + subject.should_receive(:process_cmd).with(%w(git-upload-pack gitlab-ci.git)) end it "should execute the command" do @@ -185,13 +200,13 @@ describe GitlabShell do context 'gitaly-upload-pack' do let(:ssh_cmd) { "git-upload-pack gitlab-ci.git" } - before { + before do api.stub(check_access: gitaly_check_access) - } + end after { subject.exec(ssh_cmd) } it "should process the command" do - subject.should_receive(:process_cmd).with(%W(git-upload-pack gitlab-ci.git)) + subject.should_receive(:process_cmd).with(%w(git-upload-pack gitlab-ci.git)) end it "should execute the command" do @@ -215,7 +230,7 @@ describe GitlabShell do after { subject.exec(ssh_cmd) } it "should process the command" do - subject.should_receive(:process_cmd).with(%W(git-receive-pack gitlab-ci.git)) + subject.should_receive(:process_cmd).with(%w(git-receive-pack gitlab-ci.git)) end it "should execute the command" do @@ -231,13 +246,13 @@ describe GitlabShell do context 'gitaly-receive-pack' do let(:ssh_cmd) { "git-receive-pack gitlab-ci.git" } - before { + before do api.stub(check_access: gitaly_check_access) - } + end after { subject.exec(ssh_cmd) } it "should process the command" do - subject.should_receive(:process_cmd).with(%W(git-receive-pack gitlab-ci.git)) + subject.should_receive(:process_cmd).with(%w(git-receive-pack gitlab-ci.git)) end it "should execute the command" do @@ -264,7 +279,7 @@ describe GitlabShell do after { subject.exec(ssh_cmd) } it "should process the command" do - subject.should_receive(:process_cmd).with(%W(git-upload-archive gitlab-ci.git)) + subject.should_receive(:process_cmd).with(%w(git-upload-archive gitlab-ci.git)) end it "should execute the command" do @@ -341,9 +356,9 @@ describe GitlabShell do context "failed connection" do let(:ssh_cmd) { 'git-upload-pack gitlab-ci.git' } - before { + before do api.stub(:check_access).and_raise(GitlabNet::ApiUnreachableError) - } + end after { subject.exec(ssh_cmd) } it "should not process the command" do @@ -382,9 +397,9 @@ describe GitlabShell do context 'when the process is unsuccessful' do it 'displays the error to the user' do api.stub(two_factor_recovery_codes: { - 'success' => false, - 'message' => 'Could not find the given key' - }) + 'success' => false, + 'message' => 'Could not find the given key' + }) expect($stdout).to receive(:puts) .with(/Could not find the given key/) @@ -412,7 +427,8 @@ describe GitlabShell do gl_id: nil, gl_username: nil, repository_path: nil, - gitaly: nil)) + gitaly: nil, + git_protocol: nil)) message = 'Access denied' user_string = "user with id #{gl_id}" $logger.should_receive(:warn).with(message, command: 'git-upload-pack gitlab-ci.git', user: user_string) @@ -457,6 +473,7 @@ describe GitlabShell do before do Kernel.stub(:exec) shell.gl_repository = gl_repository + shell.git_protocol = git_protocol shell.instance_variable_set(:@username, gl_username) end