Commit 48f1a61f authored by Patricio Cano's avatar Patricio Cano

Refactored LFS auth logic when using SSH to use its own API endpoint...

Refactored LFS auth logic when using SSH to use its own API endpoint `/lfs_authenticate` and added tests.
parent cb85cf1f
...@@ -69,12 +69,26 @@ module API ...@@ -69,12 +69,26 @@ module API
else else
project.repository.path_to_repo project.repository.path_to_repo
end end
end
# Return HTTP full path, so that gitlab-shell has this information response
# ready for git-lfs-authenticate end
response[:repository_http_path] = project.http_url_to_repo
post "/lfs_authenticate" do
status 200
key = Key.find(params[:key_id])
user = key.user
if user
token = Gitlab::LfsToken.new(user).generate
response = { username: user.username, lfs_token: token }
else
token = Gitlab::LfsToken.new(key).generate
response = { username: "lfs-deploy-key-#{key.id}", lfs_token: token }
end end
response[:repository_http_path] = project.http_url_to_repo
response response
end end
...@@ -87,15 +101,7 @@ module API ...@@ -87,15 +101,7 @@ module API
# #
get "/discover" do get "/discover" do
key = Key.find(params[:key_id]) key = Key.find(params[:key_id])
user = key.user present key.user, with: Entities::UserSafe
if user
token = Gitlab::LfsToken.new(user).set_token
{ name: user.name, username: user.username, lfs_token: token }
else
token = Gitlab::LfsToken.new(key).set_token
{ username: "lfs-deploy-key-#{key.id}", lfs_token: token }
end
end end
get "/check" do get "/check" do
......
...@@ -119,11 +119,11 @@ module Gitlab ...@@ -119,11 +119,11 @@ module Gitlab
def lfs_token_check(login, password) def lfs_token_check(login, password)
if login.include?('lfs-deploy-key') if login.include?('lfs-deploy-key')
key = DeployKey.find(login.gsub('lfs-deploy-key-', '')) key = DeployKey.find(login.gsub('lfs-deploy-key-', ''))
token = Gitlab::LfsToken.new(key).get_value token = Gitlab::LfsToken.new(key).value
Result.new(key, :lfs_deploy_token) if key && token == password Result.new(key, :lfs_deploy_token) if key && token == password
else else
user = User.by_login(login) user = User.by_login(login)
token = Gitlab::LfsToken.new(user).get_value token = Gitlab::LfsToken.new(user).value
Result.new(user, :lfs_token) if user && token == password Result.new(user, :lfs_token) if user && token == password
end end
end end
......
...@@ -6,15 +6,17 @@ module Gitlab ...@@ -6,15 +6,17 @@ module Gitlab
@actor = actor @actor = actor
end end
def set_token def generate
token = Devise.friendly_token(50) token = Devise.friendly_token(50)
Gitlab::Redis.with do |redis| Gitlab::Redis.with do |redis|
redis.set(redis_key, token, ex: 3600) redis.set(redis_key, token, ex: 600)
end end
token token
end end
def get_value def value
Gitlab::Redis.with do |redis| Gitlab::Redis.with do |redis|
redis.get(redis_key) redis.get(redis_key)
end end
......
...@@ -26,7 +26,7 @@ describe Gitlab::Auth, lib: true do ...@@ -26,7 +26,7 @@ describe Gitlab::Auth, lib: true do
it 'recognizes user lfs tokens' do it 'recognizes user lfs tokens' do
user = create(:user) user = create(:user)
ip = 'ip' ip = 'ip'
token = Gitlab::LfsToken.new(user).set_token token = Gitlab::LfsToken.new(user).generate
expect(gl_auth).to receive(:rate_limit!).with(ip, success: true, login: user.username) expect(gl_auth).to receive(:rate_limit!).with(ip, success: true, login: user.username)
expect(gl_auth.find_for_git_client(user.username, token, project: nil, ip: ip)).to eq(Gitlab::Auth::Result.new(user, :lfs_token)) expect(gl_auth.find_for_git_client(user.username, token, project: nil, ip: ip)).to eq(Gitlab::Auth::Result.new(user, :lfs_token))
...@@ -35,7 +35,7 @@ describe Gitlab::Auth, lib: true do ...@@ -35,7 +35,7 @@ describe Gitlab::Auth, lib: true do
it 'recognizes deploy key lfs tokens' do it 'recognizes deploy key lfs tokens' do
key = create(:deploy_key) key = create(:deploy_key)
ip = 'ip' ip = 'ip'
token = Gitlab::LfsToken.new(key).set_token token = Gitlab::LfsToken.new(key).generate
expect(gl_auth).to receive(:rate_limit!).with(ip, success: true, login: "lfs-deploy-key-#{key.id}") expect(gl_auth).to receive(:rate_limit!).with(ip, success: true, login: "lfs-deploy-key-#{key.id}")
expect(gl_auth.find_for_git_client("lfs-deploy-key-#{key.id}", token, project: nil, ip: ip)).to eq(Gitlab::Auth::Result.new(key, :lfs_deploy_token)) expect(gl_auth.find_for_git_client("lfs-deploy-key-#{key.id}", token, project: nil, ip: ip)).to eq(Gitlab::Auth::Result.new(key, :lfs_deploy_token))
......
...@@ -4,7 +4,7 @@ describe Gitlab::LfsToken, lib: true do ...@@ -4,7 +4,7 @@ describe Gitlab::LfsToken, lib: true do
describe '#set_token and #get_value' do describe '#set_token and #get_value' do
shared_examples 'an LFS token generator' do shared_examples 'an LFS token generator' do
it 'returns a randomly generated token' do it 'returns a randomly generated token' do
token = handler.set_token token = handler.generate
expect(token).not_to be_nil expect(token).not_to be_nil
expect(token).to be_a String expect(token).to be_a String
...@@ -12,9 +12,9 @@ describe Gitlab::LfsToken, lib: true do ...@@ -12,9 +12,9 @@ describe Gitlab::LfsToken, lib: true do
end end
it 'returns the correct token based on the key' do it 'returns the correct token based on the key' do
token = handler.set_token token = handler.generate
expect(handler.get_value).to eq(token) expect(handler.value).to eq(token)
end end
end end
......
...@@ -100,15 +100,20 @@ describe API::API, api: true do ...@@ -100,15 +100,20 @@ describe API::API, api: true do
end end
end end
describe "GET /internal/discover" do describe "POST /internal/lfs_authenticate" do
before do
project.team << [user, :developer]
end
context 'user key' do context 'user key' do
it 'returns the correct information about the key' do it 'returns the correct information about the key' do
get(api("/internal/discover"), key_id: key.id, secret_token: secret_token) lfs_auth(key, project)
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
expect(json_response['username']).to eq(user.username)
expect(json_response['lfs_token']).to eq(Gitlab::LfsToken.new(user).value)
expect(json_response['name']).to eq(user.name) expect(json_response['repository_http_path']).to eq(project.http_url_to_repo)
expect(json_response['lfs_token']).to eq(Gitlab::LfsToken.new(user).get_value)
end end
end end
...@@ -116,16 +121,26 @@ describe API::API, api: true do ...@@ -116,16 +121,26 @@ describe API::API, api: true do
let(:key) { create(:deploy_key) } let(:key) { create(:deploy_key) }
it 'returns the correct information about the key' do it 'returns the correct information about the key' do
get(api("/internal/discover"), key_id: key.id, secret_token: secret_token) lfs_auth(key, project)
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
expect(json_response['username']).to eq("lfs-deploy-key-#{key.id}") expect(json_response['username']).to eq("lfs-deploy-key-#{key.id}")
expect(json_response['lfs_token']).to eq(Gitlab::LfsToken.new(key).get_value) expect(json_response['lfs_token']).to eq(Gitlab::LfsToken.new(key).value)
expect(json_response['repository_http_path']).to eq(project.http_url_to_repo)
end end
end end
end end
describe "GET /internal/discover" do
it do
get(api("/internal/discover"), key_id: key.id, secret_token: secret_token)
expect(response).to have_http_status(200)
expect(json_response['name']).to eq(user.name)
end
end
describe "POST /internal/allowed" do describe "POST /internal/allowed" do
context "access granted" do context "access granted" do
before do before do
...@@ -159,7 +174,6 @@ describe API::API, api: true do ...@@ -159,7 +174,6 @@ describe API::API, api: true do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
expect(json_response["status"]).to be_truthy expect(json_response["status"]).to be_truthy
expect(json_response["repository_path"]).to eq(project.repository.path_to_repo) expect(json_response["repository_path"]).to eq(project.repository.path_to_repo)
expect(json_response["repository_http_path"]).to eq(project.http_url_to_repo)
end end
end end
...@@ -170,7 +184,6 @@ describe API::API, api: true do ...@@ -170,7 +184,6 @@ describe API::API, api: true do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
expect(json_response["status"]).to be_truthy expect(json_response["status"]).to be_truthy
expect(json_response["repository_path"]).to eq(project.repository.path_to_repo) expect(json_response["repository_path"]).to eq(project.repository.path_to_repo)
expect(json_response["repository_http_path"]).to eq(project.http_url_to_repo)
end end
end end
end end
...@@ -407,4 +420,13 @@ describe API::API, api: true do ...@@ -407,4 +420,13 @@ describe API::API, api: true do
protocol: 'ssh' protocol: 'ssh'
) )
end end
def lfs_auth(key, project)
post(
api("/internal/lfs_authenticate"),
key_id: key.id,
secret_token: secret_token,
project: project.path_with_namespace
)
end
end end
...@@ -917,7 +917,7 @@ describe 'Git LFS API and storage' do ...@@ -917,7 +917,7 @@ describe 'Git LFS API and storage' do
end end
def authorize_deploy_key def authorize_deploy_key
ActionController::HttpAuthentication::Basic.encode_credentials("lfs-deploy-key-#{key.id}", Gitlab::LfsToken.new(key).set_token) ActionController::HttpAuthentication::Basic.encode_credentials("lfs-deploy-key-#{key.id}", Gitlab::LfsToken.new(key).generate)
end end
def fork_project(project, user, object = nil) def fork_project(project, user, object = nil)
......
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