Skip to content

Commit f53d09e

Browse files
committed
Refactored LFS auth logic to use its own API endpoint.
1 parent c16f732 commit f53d09e

11 files changed

+107
-28
lines changed

lib/gitlab_access_status.rb

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
require 'json'
22

33
class GitAccessStatus
4-
attr_reader :message, :repository_path, :repository_http_path
4+
attr_reader :message, :repository_path
55

6-
def initialize(status, message, repository_path, repository_http_path)
6+
def initialize(status, message, repository_path)
77
@status = status
88
@message = message
99
@repository_path = repository_path
10-
@repository_http_path = repository_http_path
1110
end
1211

1312
def self.create_from_json(json)
1413
values = JSON.parse(json)
15-
self.new(values["status"], values["message"], values["repository_path"], values["repository_http_path"])
14+
self.new(values["status"], values["message"], values["repository_path"])
1615
end
1716

1817
def allowed?

lib/gitlab_lfs_authentication.rb

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,23 @@
22
require 'json'
33

44
class GitlabLfsAuthentication
5-
attr_accessor :user, :repository_http_path
5+
attr_accessor :username, :lfs_token, :repository_http_path
66

7-
def initialize(user, repository_http_path)
8-
@user = user
7+
def initialize(username, lfs_token, repository_http_path)
8+
@username = username
9+
@lfs_token = lfs_token
910
@repository_http_path = repository_http_path
1011
end
1112

13+
def self.build_from_json(json)
14+
values = JSON.parse(json)
15+
self.new(values['username'], values['lfs_token'], values['repository_http_path'])
16+
end
17+
1218
def authenticate!
1319
authorization = {
1420
header: {
15-
Authorization: "Basic #{Base64.strict_encode64("#{user['username']}:#{user['lfs_token']}")}"
21+
Authorization: "Basic #{Base64.strict_encode64("#{username}:#{lfs_token}")}"
1622
},
1723
href: "#{repository_http_path}/info/lfs/"
1824
}

lib/gitlab_net.rb

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
require_relative 'gitlab_logger'
77
require_relative 'gitlab_access'
88
require_relative 'gitlab_redis'
9+
require_relative 'gitlab_lfs_authentication'
910
require_relative 'httpunix'
1011

1112
class GitlabNet
@@ -15,15 +16,12 @@ class ApiUnreachableError < StandardError; end
1516
READ_TIMEOUT = 300
1617

1718
def check_access(cmd, repo, actor, changes, protocol)
18-
project_name = repo.gsub("'", "")
19-
project_name = project_name.gsub(/\.git\Z/, "")
20-
project_name = project_name.gsub(/\A\//, "")
2119
changes = changes.join("\n") unless changes.kind_of?(String)
2220

2321
params = {
2422
action: cmd,
2523
changes: changes,
26-
project: project_name,
24+
project: project_name(repo),
2725
protocol: protocol
2826
}
2927

@@ -39,7 +37,7 @@ def check_access(cmd, repo, actor, changes, protocol)
3937
if resp.code == '200'
4038
GitAccessStatus.create_from_json(resp.body)
4139
else
42-
GitAccessStatus.new(false, 'API is not accessible', nil, nil)
40+
GitAccessStatus.new(false, 'API is not accessible', nil)
4341
end
4442
end
4543

@@ -49,6 +47,19 @@ def discover(key)
4947
JSON.parse(resp.body) rescue nil
5048
end
5149

50+
def lfs_authenticate(key, repo)
51+
params = {
52+
project: project_name(repo),
53+
key_id: key.gsub('key-', '')
54+
}
55+
56+
resp = post("#{host}/lfs_authenticate", params)
57+
58+
if resp.code == '200'
59+
GitlabLfsAuthentication.build_from_json(resp.body)
60+
end
61+
end
62+
5263
def broadcast_message
5364
resp = get("#{host}/broadcast_message")
5465
JSON.parse(resp.body) rescue {}
@@ -107,6 +118,12 @@ def redis_client
107118

108119
protected
109120

121+
def project_name(repo)
122+
project_name = repo.gsub("'", "")
123+
project_name = project_name.gsub(/\.git\Z/, "")
124+
project_name.gsub(/\A\//, "")
125+
end
126+
110127
def config
111128
@config ||= GitlabConfig.new
112129
end

lib/gitlab_shell.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
require 'shellwords'
22

33
require_relative 'gitlab_net'
4-
require_relative 'gitlab_lfs_authentication'
54

65
class GitlabShell
76
class AccessDeniedError < StandardError; end
@@ -12,7 +11,7 @@ class InvalidRepositoryPathError < StandardError; end
1211
API_COMMANDS = %w(2fa_recovery_codes)
1312
GL_PROTOCOL = 'ssh'.freeze
1413

15-
attr_accessor :key_id, :repo_name, :command, :git_access, :repository_http_path
14+
attr_accessor :key_id, :repo_name, :command, :git_access
1615
attr_reader :repo_path
1716

1817
def initialize(key_id)
@@ -95,7 +94,6 @@ def verify_access
9594
raise AccessDeniedError, status.message unless status.allowed?
9695

9796
self.repo_path = status.repository_path
98-
@repository_http_path = status.repository_http_path
9997
end
10098

10199
def process_cmd(args)
@@ -192,9 +190,11 @@ def gcryptsetup?(args)
192190
end
193191

194192
def lfs_authenticate
195-
return unless user
193+
lfs_access = api.lfs_authenticate(@key_id, @repo_name)
196194

197-
puts GitlabLfsAuthentication.new(user, repository_http_path).authenticate!
195+
return unless lfs_access
196+
197+
puts lfs_access.authenticate!
198198
end
199199

200200
private

spec/gitlab_access_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
let(:repo_path) { File.join(repository_path, repo_name) + ".git" }
88
let(:api) do
99
double(GitlabNet).tap do |api|
10-
api.stub(check_access: GitAccessStatus.new(true, 'ok', '/home/git/repositories', 'http://gitlab.dev/repo'))
10+
api.stub(check_access: GitAccessStatus.new(true, 'ok', '/home/git/repositories'))
1111
end
1212
end
1313
subject do
@@ -39,7 +39,7 @@
3939
context "access is denied" do
4040

4141
before do
42-
api.stub(check_access: GitAccessStatus.new(false, 'denied', nil, nil))
42+
api.stub(check_access: GitAccessStatus.new(false, 'denied', nil))
4343
end
4444

4545
it "returns false" do

spec/gitlab_lfs_authentication_spec.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@
55
let(:user) { { 'username' => 'dzaporozhets', 'lfs_token' => 'wsnys8Zm8Jn7zyhHTAAK' } }
66

77
subject do
8-
GitlabLfsAuthentication.new(user, 'http://gitlab.dev/repo')
8+
GitlabLfsAuthentication.new('dzaporozhets', 'wsnys8Zm8Jn7zyhHTAAK', 'http://gitlab.dev/repo')
99
end
1010

1111
describe '#initialize' do
12-
it { subject.user.should == user }
12+
it { subject.username.should == 'dzaporozhets' }
13+
it { subject.lfs_token.should == 'wsnys8Zm8Jn7zyhHTAAK' }
1314
it { subject.repository_http_path.should == 'http://gitlab.dev/repo' }
1415
end
1516

spec/gitlab_net_spec.rb

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
VCR.use_cassette("discover-ok") do
3939
user = gitlab_net.discover('key-126')
4040
user['name'].should == 'Dmitriy Zaporozhets'
41-
user['lfs_token'].should == 'wsnys8Zm8Jn7zyhHTAAK'
4241
user['username'].should == 'dzaporozhets'
4342
end
4443
end
@@ -58,6 +57,19 @@
5857
end
5958
end
6059

60+
describe '#lfs_authenticate' do
61+
context 'lfs authentication succeeded' do
62+
it 'should return the correct data' do
63+
VCR.use_cassette('lfs-authenticate-ok') do
64+
lfs_access = gitlab_net.lfs_authenticate('key-126', 'gitlab/gitlabhq.git')
65+
lfs_access.username.should == 'dzaporozhets'
66+
lfs_access.lfs_token.should == 'wsnys8Zm8Jn7zyhHTAAK'
67+
lfs_access.repository_http_path.should == 'http://gitlab.dev/gitlab/gitlabhq.git'
68+
end
69+
end
70+
end
71+
end
72+
6173
describe :broadcast_message do
6274
context "broadcast message exists" do
6375
it 'should return message' do
@@ -132,7 +144,6 @@
132144
VCR.use_cassette("allowed-pull") do
133145
access = gitlab_net.check_access('git-receive-pack', 'gitlab/gitlabhq.git', 'key-126', changes, 'ssh')
134146
access.allowed?.should be_true
135-
access.repository_http_path.should == 'http://gitlab.dev/gitlab/gitlabhq.git'
136147
end
137148
end
138149

spec/gitlab_shell_spec.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636

3737
let(:repo_name) { 'gitlab-ci.git' }
3838
let(:repo_path) { File.join(tmp_repos_path, repo_name) }
39-
let(:repo_http_path) { 'http://gitlab.dev/dzaporozhets/gitlab.git' }
4039

4140
before do
4241
GitlabConfig.any_instance.stub(audit_usernames: false)
@@ -333,7 +332,7 @@
333332
end
334333

335334
it "should disallow access and log the attempt if check_access returns false status" do
336-
api.stub(check_access: GitAccessStatus.new(false, 'denied', nil, nil))
335+
api.stub(check_access: GitAccessStatus.new(false, 'denied', nil))
337336
message = "gitlab-shell: Access denied for git command <git-upload-pack gitlab-ci.git> "
338337
message << "by user with key #{key_id}."
339338
$logger.should_receive(:warn).with(message)

spec/vcr_cassettes/allowed-pull.yml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

spec/vcr_cassettes/discover-ok.yml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)