summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatricio Cano <suprnova32@gmail.com>2016-08-25 17:34:34 -0500
committerPatricio Cano <suprnova32@gmail.com>2016-09-06 12:06:45 -0500
commitdbf374e10ad859a02ef69af53031e245913b6e65 (patch)
tree304e387c2702db9f9685f8a951ef3d65c60ad09c
parentc6d8af599dc797ec8ba7874380abad393b439c9e (diff)
downloadgitlab-shell-dbf374e10ad859a02ef69af53031e245913b6e65.tar.gz
Added LFS support to SSH
- Required changes to GitLab Shell include the actual handling of the `git-lfs-authenticate` command and the retrieval of the correct credentials.
-rw-r--r--CHANGELOG1
-rw-r--r--lib/gitlab_access_status.rb7
-rw-r--r--lib/gitlab_net.rb2
-rw-r--r--lib/gitlab_shell.rb23
-rw-r--r--spec/gitlab_access_spec.rb4
-rw-r--r--spec/gitlab_net_spec.rb3
-rw-r--r--spec/gitlab_shell_spec.rb16
-rw-r--r--spec/vcr_cassettes/allowed-pull.yml2
-rw-r--r--spec/vcr_cassettes/discover-ok.yml2
9 files changed, 50 insertions, 10 deletions
diff --git a/CHANGELOG b/CHANGELOG
index bce8783..bd2a2a4 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,6 @@
v3.5.0
- Add option to recover 2FA via SSH
+ - Added full support for `git-lfs-authenticate` to properly handle LFS requests and pass them on to Workhorse
v3.4.0
- Redis Sentinel support
diff --git a/lib/gitlab_access_status.rb b/lib/gitlab_access_status.rb
index 7fb88be..1ae0528 100644
--- a/lib/gitlab_access_status.rb
+++ b/lib/gitlab_access_status.rb
@@ -1,17 +1,18 @@
require 'json'
class GitAccessStatus
- attr_reader :message, :repository_path
+ attr_reader :message, :repository_path, :repository_http_path
- def initialize(status, message, repository_path)
+ def initialize(status, message, repository_path, repository_http_path)
@status = status
@message = message
@repository_path = repository_path
+ @repository_http_path = repository_http_path
end
def self.create_from_json(json)
values = JSON.parse(json)
- self.new(values["status"], values["message"], values["repository_path"])
+ self.new(values["status"], values["message"], values["repository_path"], values["repository_http_path"])
end
def allowed?
diff --git a/lib/gitlab_net.rb b/lib/gitlab_net.rb
index 47bae95..42ff94c 100644
--- a/lib/gitlab_net.rb
+++ b/lib/gitlab_net.rb
@@ -39,7 +39,7 @@ class GitlabNet
if resp.code == '200'
GitAccessStatus.create_from_json(resp.body)
else
- GitAccessStatus.new(false, 'API is not accessible', nil)
+ GitAccessStatus.new(false, 'API is not accessible', nil, nil)
end
end
diff --git a/lib/gitlab_shell.rb b/lib/gitlab_shell.rb
index 1fdb9e5..ab98a6e 100644
--- a/lib/gitlab_shell.rb
+++ b/lib/gitlab_shell.rb
@@ -1,4 +1,6 @@
require 'shellwords'
+require 'base64'
+require 'json'
require_relative 'gitlab_net'
@@ -11,7 +13,7 @@ class GitlabShell
API_COMMANDS = %w(2fa_recovery_codes)
GL_PROTOCOL = 'ssh'.freeze
- attr_accessor :key_id, :repo_name, :command
+ attr_accessor :key_id, :repo_name, :command, :git_access, :repository_http_path
attr_reader :repo_path
def initialize(key_id)
@@ -94,6 +96,7 @@ class GitlabShell
raise AccessDeniedError, status.message unless status.allowed?
self.repo_path = status.repository_path
+ @repository_http_path = status.repository_http_path
end
def process_cmd(args)
@@ -117,6 +120,11 @@ class GitlabShell
$logger.info "gitlab-shell: executing git-annex command <#{parsed_args.join(' ')}> for #{log_username}."
exec_cmd(*parsed_args)
+
+ elsif @command == 'git-lfs-authenticate'
+ $logger.info "gitlab-shell: Processing LFS authentication for #{log_username}."
+ lfs_authenticate
+
else
$logger.info "gitlab-shell: executing git command <#{@command} #{repo_path}> for #{log_username}."
exec_cmd(@command, repo_path)
@@ -184,6 +192,19 @@ class GitlabShell
non_dashed[0, 2] == %w{git-annex-shell gcryptsetup}
end
+ def lfs_authenticate
+ return unless user
+
+ authorization = {
+ header: {
+ Authorization: "Basic #{Base64.strict_encode64("#{user['username']}:#{user['lfs_token']}")}"
+ },
+ href: "#{repository_http_path}/info/lfs/"
+ }
+
+ puts JSON.generate(authorization)
+ end
+
private
def continue?(question)
diff --git a/spec/gitlab_access_spec.rb b/spec/gitlab_access_spec.rb
index 2781aa9..e2a0c77 100644
--- a/spec/gitlab_access_spec.rb
+++ b/spec/gitlab_access_spec.rb
@@ -7,7 +7,7 @@ describe GitlabAccess do
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, 'ok', '/home/git/repositories'))
+ api.stub(check_access: GitAccessStatus.new(true, 'ok', '/home/git/repositories', 'http://gitlab.dev/repo'))
end
end
subject do
@@ -39,7 +39,7 @@ describe GitlabAccess do
context "access is denied" do
before do
- api.stub(check_access: GitAccessStatus.new(false, 'denied', nil))
+ api.stub(check_access: GitAccessStatus.new(false, 'denied', nil, nil))
end
it "returns false" do
diff --git a/spec/gitlab_net_spec.rb b/spec/gitlab_net_spec.rb
index bcd0d79..cee5b91 100644
--- a/spec/gitlab_net_spec.rb
+++ b/spec/gitlab_net_spec.rb
@@ -38,6 +38,8 @@ describe GitlabNet, vcr: true do
VCR.use_cassette("discover-ok") do
user = gitlab_net.discover('key-126')
user['name'].should == 'Dmitriy Zaporozhets'
+ user['lfs_token'].should == 'wsnys8Zm8Jn7zyhHTAAK'
+ user['username'].should == 'dzaporozhets'
end
end
@@ -130,6 +132,7 @@ describe GitlabNet, vcr: true do
VCR.use_cassette("allowed-pull") do
access = gitlab_net.check_access('git-receive-pack', 'gitlab/gitlabhq.git', 'key-126', changes, 'ssh')
access.allowed?.should be_true
+ access.repository_http_path.should == 'http://gitlab.dev/gitlab/gitlabhq.git'
end
end
diff --git a/spec/gitlab_shell_spec.rb b/spec/gitlab_shell_spec.rb
index ea11652..378b964 100644
--- a/spec/gitlab_shell_spec.rb
+++ b/spec/gitlab_shell_spec.rb
@@ -36,6 +36,7 @@ describe GitlabShell do
let(:repo_name) { 'gitlab-ci.git' }
let(:repo_path) { File.join(tmp_repos_path, repo_name) }
+ let(:repo_http_path) { 'http://gitlab.dev/dzaporozhets/gitlab.git' }
before do
GitlabConfig.any_instance.stub(audit_usernames: false)
@@ -112,6 +113,19 @@ describe GitlabShell do
its(:repo_name) { should == 'dzaporozhets/gitlab.git' }
its(:command) { should == 'git-annex-shell' }
end
+
+ describe 'git-lfs' do
+ let(:repo_name) { 'dzaporozhets/gitlab.git' }
+ let(:ssh_args) { %W(git-lfs-authenticate dzaporozhets/gitlab.git download) }
+
+ before do
+ subject.send :parse_cmd, ssh_args
+ end
+
+ its(:repo_name) { should == 'dzaporozhets/gitlab.git' }
+ its(:command) { should == 'git-lfs-authenticate' }
+ its(:git_access) { should == 'git-upload-pack' }
+ end
end
describe :exec do
@@ -306,7 +320,7 @@ describe GitlabShell do
end
it "should disallow access and log the attempt if check_access returns false status" do
- api.stub(check_access: GitAccessStatus.new(false, 'denied', nil))
+ api.stub(check_access: GitAccessStatus.new(false, 'denied', nil, nil))
message = "gitlab-shell: Access denied for git command <git-upload-pack gitlab-ci.git> "
message << "by user with key #{key_id}."
$logger.should_receive(:warn).with(message)
diff --git a/spec/vcr_cassettes/allowed-pull.yml b/spec/vcr_cassettes/allowed-pull.yml
index 5a10ec9..8e01cd3 100644
--- a/spec/vcr_cassettes/allowed-pull.yml
+++ b/spec/vcr_cassettes/allowed-pull.yml
@@ -42,7 +42,7 @@ http_interactions:
- '0.089741'
body:
encoding: UTF-8
- string: '{"status": "true"}'
+ string: '{"status": "true","repository_http_path": "http://gitlab.dev/gitlab/gitlabhq.git"}'
http_version:
recorded_at: Wed, 03 Sep 2014 11:27:36 GMT
recorded_with: VCR 2.4.0
diff --git a/spec/vcr_cassettes/discover-ok.yml b/spec/vcr_cassettes/discover-ok.yml
index a86243c..c2cee40 100644
--- a/spec/vcr_cassettes/discover-ok.yml
+++ b/spec/vcr_cassettes/discover-ok.yml
@@ -40,7 +40,7 @@ http_interactions:
- '0.016934'
body:
encoding: UTF-8
- string: '{"name":"Dmitriy Zaporozhets","username":"dzaporozhets"}'
+ string: '{"name":"Dmitriy Zaporozhets","username":"dzaporozhets","lfs_token":"wsnys8Zm8Jn7zyhHTAAK"}'
http_version:
recorded_at: Wed, 03 Sep 2014 11:27:35 GMT
recorded_with: VCR 2.4.0