Commit 5c158002 authored by Nick Thomas's avatar Nick Thomas

Merge branch 'add-protocol-v2-logic' into 'master'

Add Git protocol v2

See merge request gitlab-org/gitlab-shell!217
parents e3fead94 66e00351
v8.0.0 v8.0.0
- SSH certificate support (!207) - SSH certificate support (!207)
- Support Git v2 protocol (!217)
v7.2.0 v7.2.0
- Update gitaly-proto to 0.109.0 (!216) - Update gitaly-proto to 0.109.0 (!216)
......
require 'json' require 'json'
class GitAccessStatus 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 @status = status
@message = message @message = message
@gl_repository = gl_repository @gl_repository = gl_repository
...@@ -11,6 +11,7 @@ class GitAccessStatus ...@@ -11,6 +11,7 @@ class GitAccessStatus
@gl_username = gl_username @gl_username = gl_username
@repository_path = repository_path @repository_path = repository_path
@gitaly = gitaly @gitaly = gitaly
@git_protocol = git_protocol
end end
def self.create_from_json(json) def self.create_from_json(json)
...@@ -21,7 +22,8 @@ class GitAccessStatus ...@@ -21,7 +22,8 @@ class GitAccessStatus
gl_id: values["gl_id"], gl_id: values["gl_id"],
gl_username: values["gl_username"], gl_username: values["gl_username"],
repository_path: values["repository_path"], repository_path: values["repository_path"],
gitaly: values["gitaly"]) gitaly: values["gitaly"],
git_protocol: values["git_protocol"])
end end
def allowed? def allowed?
......
...@@ -44,7 +44,8 @@ class GitlabNet # rubocop:disable Metrics/ClassLength ...@@ -44,7 +44,8 @@ class GitlabNet # rubocop:disable Metrics/ClassLength
gl_id: nil, gl_id: nil,
gl_username: nil, gl_username: nil,
repository_path: nil, repository_path: nil,
gitaly: nil) gitaly: nil,
git_protocol: nil)
end end
end end
......
...@@ -18,7 +18,7 @@ class GitlabShell # rubocop:disable Metrics/ClassLength ...@@ -18,7 +18,7 @@ class GitlabShell # rubocop:disable Metrics/ClassLength
API_COMMANDS = %w(2fa_recovery_codes).freeze API_COMMANDS = %w(2fa_recovery_codes).freeze
GL_PROTOCOL = 'ssh'.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 attr_reader :repo_path
def initialize(who) def initialize(who)
...@@ -118,6 +118,7 @@ class GitlabShell # rubocop:disable Metrics/ClassLength ...@@ -118,6 +118,7 @@ class GitlabShell # rubocop:disable Metrics/ClassLength
self.repo_path = status.repository_path self.repo_path = status.repository_path
@gl_repository = status.gl_repository @gl_repository = status.gl_repository
@git_protocol = ENV['GIT_PROTOCOL']
@gitaly = status.gitaly @gitaly = status.gitaly
@username = status.gl_username @username = status.gl_username
if defined?(@who) if defined?(@who)
...@@ -150,7 +151,8 @@ class GitlabShell # rubocop:disable Metrics/ClassLength ...@@ -150,7 +151,8 @@ class GitlabShell # rubocop:disable Metrics/ClassLength
'repository' => @gitaly['repository'], 'repository' => @gitaly['repository'],
'gl_repository' => @gl_repository, 'gl_repository' => @gl_repository,
'gl_id' => @gl_id, 'gl_id' => @gl_id,
'gl_username' => @username 'gl_username' => @username,
'git_protocol' => @git_protocol
} }
args = [gitaly_address, JSON.dump(gitaly_request)] args = [gitaly_address, JSON.dump(gitaly_request)]
......
...@@ -3,8 +3,8 @@ require 'gitlab_access' ...@@ -3,8 +3,8 @@ require 'gitlab_access'
describe GitlabAccess do describe GitlabAccess do
let(:repository_path) { "/home/git/repositories" } let(:repository_path) { "/home/git/repositories" }
let(:repo_name) { 'dzaporozhets/gitlab-ci' } let(:repo_name) { 'dzaporozhets/gitlab-ci' }
let(:repo_path) { File.join(repository_path, repo_name) + ".git" } let(:repo_path) { File.join(repository_path, repo_name) + ".git" }
let(:api) do let(:api) do
double(GitlabNet).tap do |api| double(GitlabNet).tap do |api|
api.stub(check_access: GitAccessStatus.new(true, api.stub(check_access: GitAccessStatus.new(true,
...@@ -13,7 +13,8 @@ describe GitlabAccess do ...@@ -13,7 +13,8 @@ describe GitlabAccess do
gl_id: 'user-123', gl_id: 'user-123',
gl_username: 'testuser', gl_username: 'testuser',
repository_path: '/home/git/repositories', repository_path: '/home/git/repositories',
gitaly: nil)) gitaly: nil,
git_protocol: 'version=2'))
end end
end end
subject do subject do
...@@ -35,14 +36,12 @@ describe GitlabAccess do ...@@ -35,14 +36,12 @@ describe GitlabAccess do
describe "#exec" do describe "#exec" do
context "access is granted" do context "access is granted" do
it "returns true" do it "returns true" do
expect(subject.exec).to be_truthy expect(subject.exec).to be_truthy
end end
end end
context "access is denied" do context "access is denied" do
before do before do
api.stub(check_access: GitAccessStatus.new( api.stub(check_access: GitAccessStatus.new(
false, false,
...@@ -51,7 +50,8 @@ describe GitlabAccess do ...@@ -51,7 +50,8 @@ describe GitlabAccess do
gl_id: nil, gl_id: nil,
gl_username: nil, gl_username: nil,
repository_path: nil, repository_path: nil,
gitaly: nil gitaly: nil,
git_protocol: nil
)) ))
end end
...@@ -61,7 +61,6 @@ describe GitlabAccess do ...@@ -61,7 +61,6 @@ describe GitlabAccess do
end end
context "API connection fails" do context "API connection fails" do
before do before do
api.stub(:check_access).and_raise(GitlabNet::ApiUnreachableError) api.stub(:check_access).and_raise(GitlabNet::ApiUnreachableError)
end end
......
...@@ -27,7 +27,8 @@ describe GitlabShell do ...@@ -27,7 +27,8 @@ describe GitlabShell do
gl_id: gl_id, gl_id: gl_id,
gl_username: gl_username, gl_username: gl_username,
repository_path: repo_path, 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 ...@@ -41,11 +42,12 @@ describe GitlabShell do
gl_id: gl_id, gl_id: gl_id,
gl_username: gl_username, gl_username: gl_username,
repository_path: repo_path, repository_path: repo_path,
gitaly: nil)) gitaly: nil,
git_protocol: git_protocol))
api.stub(two_factor_recovery_codes: { api.stub(two_factor_recovery_codes: {
'success' => true, 'success' => true,
'recovery_codes' => ['f67c514de60c4953', '41278385fc00c1e0'] 'recovery_codes' => %w[f67c514de60c4953 41278385fc00c1e0]
}) })
end end
end end
...@@ -58,6 +60,7 @@ describe GitlabShell do ...@@ -58,6 +60,7 @@ describe GitlabShell do
let(:gl_repository) { 'project-1' } let(:gl_repository) { 'project-1' }
let(:gl_id) { 'user-1' } let(:gl_id) { 'user-1' }
let(:gl_username) { 'testuser' } let(:gl_username) { 'testuser' }
let(:git_protocol) { 'version=2' }
before do before do
GitlabConfig.any_instance.stub(audit_usernames: false) GitlabConfig.any_instance.stub(audit_usernames: false)
...@@ -72,7 +75,7 @@ describe GitlabShell do ...@@ -72,7 +75,7 @@ describe GitlabShell do
describe :parse_cmd do describe :parse_cmd do
describe 'git' do describe 'git' do
context 'w/o namespace' 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 before do
subject.send :parse_cmd, ssh_args subject.send :parse_cmd, ssh_args
...@@ -84,7 +87,7 @@ describe GitlabShell do ...@@ -84,7 +87,7 @@ describe GitlabShell do
context 'namespace' do context 'namespace' do
let(:repo_name) { 'dmitriy.zaporozhets/gitlab-ci.git' } 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 before do
subject.send :parse_cmd, ssh_args subject.send :parse_cmd, ssh_args
...@@ -95,7 +98,7 @@ describe GitlabShell do ...@@ -95,7 +98,7 @@ describe GitlabShell do
end end
context 'with an invalid number of arguments' do context 'with an invalid number of arguments' do
let(:ssh_args) { %W(foobar) } let(:ssh_args) { %w(foobar) }
it "should raise an DisallowedCommandError" do it "should raise an DisallowedCommandError" do
expect { subject.send :parse_cmd, ssh_args }.to raise_error(GitlabShell::DisallowedCommandError) expect { subject.send :parse_cmd, ssh_args }.to raise_error(GitlabShell::DisallowedCommandError)
...@@ -123,7 +126,7 @@ describe GitlabShell do ...@@ -123,7 +126,7 @@ describe GitlabShell do
describe 'git-lfs' do describe 'git-lfs' do
let(:repo_name) { 'dzaporozhets/gitlab.git' } 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 before do
subject.send :parse_cmd, ssh_args subject.send :parse_cmd, ssh_args
...@@ -136,7 +139,7 @@ describe GitlabShell do ...@@ -136,7 +139,7 @@ describe GitlabShell do
describe 'git-lfs old clients' do describe 'git-lfs old clients' do
let(:repo_name) { 'dzaporozhets/gitlab.git' } 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 before do
subject.send :parse_cmd, ssh_args subject.send :parse_cmd, ssh_args
...@@ -149,14 +152,26 @@ describe GitlabShell do ...@@ -149,14 +152,26 @@ describe GitlabShell do
end end
describe :exec do 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| shared_examples_for 'upload-pack' do |command|
let(:ssh_cmd) { "#{command} gitlab-ci.git" } let(:ssh_cmd) { "#{command} gitlab-ci.git" }
after { subject.exec(ssh_cmd) } after { subject.exec(ssh_cmd) }
it "should process the command" do 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 end
it "should execute the command" do it "should execute the command" do
...@@ -185,13 +200,13 @@ describe GitlabShell do ...@@ -185,13 +200,13 @@ describe GitlabShell do
context 'gitaly-upload-pack' do context 'gitaly-upload-pack' do
let(:ssh_cmd) { "git-upload-pack gitlab-ci.git" } let(:ssh_cmd) { "git-upload-pack gitlab-ci.git" }
before { before do
api.stub(check_access: gitaly_check_access) api.stub(check_access: gitaly_check_access)
} end
after { subject.exec(ssh_cmd) } after { subject.exec(ssh_cmd) }
it "should process the command" do 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 end
it "should execute the command" do it "should execute the command" do
...@@ -215,7 +230,7 @@ describe GitlabShell do ...@@ -215,7 +230,7 @@ describe GitlabShell do
after { subject.exec(ssh_cmd) } after { subject.exec(ssh_cmd) }
it "should process the command" do 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 end
it "should execute the command" do it "should execute the command" do
...@@ -231,13 +246,13 @@ describe GitlabShell do ...@@ -231,13 +246,13 @@ describe GitlabShell do
context 'gitaly-receive-pack' do context 'gitaly-receive-pack' do
let(:ssh_cmd) { "git-receive-pack gitlab-ci.git" } let(:ssh_cmd) { "git-receive-pack gitlab-ci.git" }
before { before do
api.stub(check_access: gitaly_check_access) api.stub(check_access: gitaly_check_access)
} end
after { subject.exec(ssh_cmd) } after { subject.exec(ssh_cmd) }
it "should process the command" do 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 end
it "should execute the command" do it "should execute the command" do
...@@ -264,7 +279,7 @@ describe GitlabShell do ...@@ -264,7 +279,7 @@ describe GitlabShell do
after { subject.exec(ssh_cmd) } after { subject.exec(ssh_cmd) }
it "should process the command" do 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 end
it "should execute the command" do it "should execute the command" do
...@@ -341,9 +356,9 @@ describe GitlabShell do ...@@ -341,9 +356,9 @@ describe GitlabShell do
context "failed connection" do context "failed connection" do
let(:ssh_cmd) { 'git-upload-pack gitlab-ci.git' } let(:ssh_cmd) { 'git-upload-pack gitlab-ci.git' }
before { before do
api.stub(:check_access).and_raise(GitlabNet::ApiUnreachableError) api.stub(:check_access).and_raise(GitlabNet::ApiUnreachableError)
} end
after { subject.exec(ssh_cmd) } after { subject.exec(ssh_cmd) }
it "should not process the command" do it "should not process the command" do
...@@ -382,9 +397,9 @@ describe GitlabShell do ...@@ -382,9 +397,9 @@ describe GitlabShell do
context 'when the process is unsuccessful' do context 'when the process is unsuccessful' do
it 'displays the error to the user' do it 'displays the error to the user' do
api.stub(two_factor_recovery_codes: { api.stub(two_factor_recovery_codes: {
'success' => false, 'success' => false,
'message' => 'Could not find the given key' 'message' => 'Could not find the given key'
}) })
expect($stdout).to receive(:puts) expect($stdout).to receive(:puts)
.with(/Could not find the given key/) .with(/Could not find the given key/)
...@@ -412,7 +427,8 @@ describe GitlabShell do ...@@ -412,7 +427,8 @@ describe GitlabShell do
gl_id: nil, gl_id: nil,
gl_username: nil, gl_username: nil,
repository_path: nil, repository_path: nil,
gitaly: nil)) gitaly: nil,
git_protocol: nil))
message = 'Access denied' message = 'Access denied'
user_string = "user with id #{gl_id}" user_string = "user with id #{gl_id}"
$logger.should_receive(:warn).with(message, command: 'git-upload-pack gitlab-ci.git', user: user_string) $logger.should_receive(:warn).with(message, command: 'git-upload-pack gitlab-ci.git', user: user_string)
...@@ -457,6 +473,7 @@ describe GitlabShell do ...@@ -457,6 +473,7 @@ describe GitlabShell do
before do before do
Kernel.stub(:exec) Kernel.stub(:exec)
shell.gl_repository = gl_repository shell.gl_repository = gl_repository
shell.git_protocol = git_protocol
shell.instance_variable_set(:@username, gl_username) shell.instance_variable_set(:@username, gl_username)
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment