Commit d67a2497 authored by Ash McKenzie's avatar Ash McKenzie

New geo/proxy_git_push_ssh routes

parent 9decb78c
require 'base64'
module API
class Geo < Grape::API
resource :geo do
......@@ -40,6 +42,51 @@ module API
render_validation_error!(db_status)
end
end
# git push over SSH secondary -> primary related proxying logic
#
resource 'proxy_git_push_ssh' do
format :json
# Responsible for making HTTP GET /repo.git/info/refs?service=git-receive-pack
# request *from* secondary gitlab-shell to primary
#
params do
requires :secret_token, type: String
requires :data, type: Hash do
requires :gl_id, type: String
requires :primary_repo, type: String
end
end
post 'info_refs' do
authenticate_by_gitlab_shell_token!
params.delete(:secret_token)
resp = Gitlab::Geo::GitPushSSHProxy.new(params['data']).info_refs
status(resp.code.to_i)
{ status: true, message: nil, result: Base64.encode64(resp.body.to_s) }
end
# Responsible for making HTTP POST /repo.git/git-receive-pack
# request *from* secondary gitlab-shell to primary
#
params do
requires :secret_token, type: String
requires :data, type: Hash do
requires :gl_id, type: String
requires :primary_repo, type: String
end
requires :output, type: String, desc: 'Output from git-receive-pack'
end
post 'push' do
authenticate_by_gitlab_shell_token!
params.delete(:secret_token)
resp = Gitlab::Geo::GitPushSSHProxy.new(params['data']).push(Base64.decode64(params['output']))
status(resp.code.to_i)
{ status: true, message: nil, result: Base64.encode64(resp.body.to_s) }
end
end
end
end
end
......@@ -17,7 +17,7 @@ module EE
override :whitelisted_routes
def whitelisted_routes
super || geo_node_update_route
super || geo_node_update_route || geo_proxy_git_push_ssh_route
end
def geo_node_update_route
......@@ -33,6 +33,14 @@ module EE
WHITELISTED_GEO_ROUTES_TRACKING_DB[controller]&.include?(action)
end
end
def geo_proxy_git_push_ssh_route
routes = ::Gitlab::Middleware::ReadOnly::API_VERSIONS.map do |version|
["/api/v#{version}/geo/proxy_git_push_ssh/info_refs",
"/api/v#{version}/geo/proxy_git_push_ssh/push"]
end
routes.flatten.include?(request.path)
end
end
end
end
......
......@@ -25,7 +25,7 @@ describe API::Geo do
end
end
describe '/geo/transfers' do
describe 'GET /geo/transfers' do
before do
stub_current_geo_node(secondary_node)
end
......@@ -287,4 +287,119 @@ describe API::Geo do
it_behaves_like 'with terms enforced'
end
end
describe '/geo/proxy_git_push_ssh' do
let(:secret_token) { Gitlab::Shell.secret_token }
let(:data) { { primary_repo: 'http://localhost:3001/testuser/repo.git', gl_id: 'key-1', gl_username: 'testuser' } }
before do
stub_current_geo_node(secondary_node)
end
describe 'POST /geo/proxy_git_push_ssh/info_refs' do
context 'with all required params missing' do
it 'responds with 400' do
post api('/geo/proxy_git_push_ssh/info_refs'), nil
expect(response).to have_gitlab_http_status(400)
expect(json_response['error']).to eql('secret_token is missing, data is missing, data[gl_id] is missing, data[primary_repo] is missing')
end
end
context 'with all required params' do
let(:git_push_ssh_proxy) { double(Gitlab::Geo::GitPushSSHProxy) }
before do
allow(Gitlab::Geo::GitPushSSHProxy).to receive(:new).with(data).and_return(git_push_ssh_proxy)
end
context 'with an invalid secret_token' do
it 'responds with 401' do
post(api('/geo/proxy_git_push_ssh/info_refs'), { secret_token: 'invalid', data: data })
expect(response).to have_gitlab_http_status(401)
expect(json_response['error']).to be_nil
end
end
context 'where an exception occurs' do
it 'responds with 500' do
expect(git_push_ssh_proxy).to receive(:info_refs).and_raise('deliberate exception raised')
post api('/geo/proxy_git_push_ssh/info_refs'), { secret_token: secret_token, data: data }
expect(response).to have_gitlab_http_status(500)
expect(json_response['message']).to include('RuntimeError (deliberate exception raised)')
expect(json_response['result']).to be_nil
end
end
context 'with a valid secret token' do
let(:http_response) { double(Net::HTTPResponse, code: 200, body: 'something here') }
it 'responds with 200' do
expect(git_push_ssh_proxy).to receive(:info_refs).and_return(http_response)
post api('/geo/proxy_git_push_ssh/info_refs'), { secret_token: secret_token, data: data }
expect(response).to have_gitlab_http_status(200)
expect(json_response['result']).to eql('something+here')
end
end
end
end
describe 'POST /geo/proxy_git_push_ssh/push' do
context 'with all required params missing' do
it 'responds with 400' do
post api('/geo/proxy_git_push_ssh/push'), nil
expect(response).to have_gitlab_http_status(400)
expect(json_response['error']).to eql('secret_token is missing, data is missing, data[gl_id] is missing, data[primary_repo] is missing, output is missing')
end
end
context 'with all required params' do
let(:output) { 'output text'}
let(:git_push_ssh_proxy) { double(Gitlab::Geo::GitPushSSHProxy) }
before do
allow(Gitlab::Geo::GitPushSSHProxy).to receive(:new).with(data).and_return(git_push_ssh_proxy)
end
context 'with an invalid secret_token' do
it 'responds with 401' do
post(api('/geo/proxy_git_push_ssh/push'), { secret_token: 'invalid', data: data, output: output })
expect(response).to have_gitlab_http_status(401)
expect(json_response['error']).to be_nil
end
end
context 'where an exception occurs' do
it 'responds with 500' do
expect(git_push_ssh_proxy).to receive(:push).and_raise('deliberate exception raised')
post api('/geo/proxy_git_push_ssh/push'), { secret_token: secret_token, data: data, output: output }
expect(response).to have_gitlab_http_status(500)
expect(json_response['message']).to include('RuntimeError (deliberate exception raised)')
expect(json_response['result']).to be_nil
end
end
context 'with a valid secret token' do
let(:http_response) { double(Net::HTTPResponse, code: 201, body: 'something here') }
it 'responds with 201' do
expect(git_push_ssh_proxy).to receive(:push).with(output).and_return(http_response)
post api('/geo/proxy_git_push_ssh/push'), { secret_token: secret_token, data: data, output: output }
expect(response).to have_gitlab_http_status(201)
expect(json_response['result']).to eql('something+here')
end
end
end
end
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