Commit 1a675dc9 authored by Ash McKenzie's avatar Ash McKenzie

Allow upload_code ability for auth'd Geo request

parent 3bcb345e
...@@ -6,11 +6,24 @@ module EE ...@@ -6,11 +6,24 @@ module EE
override :render_ok override :render_ok
def render_ok def render_ok
set_workhorse_internal_api_content_type set_workhorse_internal_api_content_type
render json: ::Gitlab::Workhorse.git_http_ok(repository, wiki?, user, action_name, show_all_refs: geo_request?) render json: ::Gitlab::Workhorse.git_http_ok(repository, wiki?, user, action_name, show_all_refs: geo_request?)
end end
private private
def user
super || geo_push_user&.user
end
def geo_push_user
@geo_push_user ||= ::Geo::PushUser.new_from_headers(request.headers)
end
def geo_push_user_headers_provided?
::Geo::PushUser.needed_headers_provided?(request.headers)
end
def geo_request? def geo_request?
::Gitlab::Geo::JwtRequestDecoder.geo_auth_attempt?(request.headers['Authorization']) ::Gitlab::Geo::JwtRequestDecoder.geo_auth_attempt?(request.headers['Authorization'])
end end
...@@ -21,9 +34,11 @@ module EE ...@@ -21,9 +34,11 @@ module EE
override :access_actor override :access_actor
def access_actor def access_actor
return :geo if geo? return super unless geo?
return :geo unless geo_push_user_headers_provided?
return geo_push_user.user if geo_push_user.user
super raise ::Gitlab::GitAccess::UnauthorizedError, 'Geo push user is invalid.'
end end
override :authenticate_user override :authenticate_user
...@@ -32,7 +47,7 @@ module EE ...@@ -32,7 +47,7 @@ module EE
payload = ::Gitlab::Geo::JwtRequestDecoder.new(request.headers['Authorization']).decode payload = ::Gitlab::Geo::JwtRequestDecoder.new(request.headers['Authorization']).decode
if payload if payload
@authentication_result = ::Gitlab::Auth::Result.new(nil, project, :geo, [:download_code]) # rubocop:disable Gitlab/ModuleWithInstanceVariables @authentication_result = ::Gitlab::Auth::Result.new(nil, project, :geo, [:download_code, :push_code]) # rubocop:disable Gitlab/ModuleWithInstanceVariables
return # grant access return # grant access
end end
......
...@@ -52,6 +52,11 @@ module EE ...@@ -52,6 +52,11 @@ module EE
def geo? def geo?
actor == :geo actor == :geo
end end
override :authed_via_jwt?
def authed_via_jwt?
geo?
end
end end
end end
end end
...@@ -268,7 +268,7 @@ For more information: #{EE::Gitlab::GeoGitAccess::GEO_SERVER_DOCS_URL}" ...@@ -268,7 +268,7 @@ For more information: #{EE::Gitlab::GeoGitAccess::GEO_SERVER_DOCS_URL}"
let(:actor) { :geo } let(:actor) { :geo }
it { expect { pull_changes }.not_to raise_error } it { expect { pull_changes }.not_to raise_error }
it { expect { push_changes }.to raise_unauthorized(Gitlab::GitAccess::ERROR_MESSAGES[:upload]) } it { expect { push_changes }.to raise_unauthorized(Gitlab::GitAccess::ERROR_MESSAGES[:push_code]) }
end end
private private
......
...@@ -13,15 +13,24 @@ describe "Git HTTP requests (Geo)" do ...@@ -13,15 +13,24 @@ describe "Git HTTP requests (Geo)" do
# Ensure the token always comes from the real time of the request # Ensure the token always comes from the real time of the request
let!(:auth_token) { Gitlab::Geo::BaseRequest.new.authorization } let!(:auth_token) { Gitlab::Geo::BaseRequest.new.authorization }
let!(:user) { create(:user) }
let!(:user_without_any_access) { create(:user) }
let!(:user_without_push_access) { create(:user) }
let!(:key) { create(:key, user: user) }
let!(:key_for_user_without_any_access) { create(:key, user: user_without_any_access) }
let!(:key_for_user_without_push_access) { create(:key, user: user_without_push_access) }
let(:env) { valid_geo_env } let(:env) { valid_geo_env }
before do before do
project.add_maintainer(user)
project.add_guest(user_without_push_access)
stub_licensed_features(geo: true) stub_licensed_features(geo: true)
stub_current_geo_node(secondary) stub_current_geo_node(current_node)
end end
shared_examples_for 'Geo sync request' do shared_examples_for 'Geo request' do
subject do subject do
make_request make_request
response response
...@@ -64,20 +73,25 @@ describe "Git HTTP requests (Geo)" do ...@@ -64,20 +73,25 @@ describe "Git HTTP requests (Geo)" do
end end
end end
context 'when current node is a secondary' do
let(:current_node) { secondary }
set(:project) { create(:project, :repository, :private) }
describe 'GET info_refs' do describe 'GET info_refs' do
context 'git pull' do context 'git pull' do
def make_request def make_request
get "/#{project.full_path}.git/info/refs", { service: 'git-upload-pack' }, env get "/#{project.full_path}.git/info/refs", { service: 'git-upload-pack' }, env
end end
it_behaves_like 'Geo sync request' it_behaves_like 'Geo request'
context 'when terms are enforced' do context 'when terms are enforced' do
before do before do
enforce_terms enforce_terms
end end
it_behaves_like 'Geo sync request' it_behaves_like 'Geo request'
end end
end end
...@@ -101,19 +115,19 @@ describe "Git HTTP requests (Geo)" do ...@@ -101,19 +115,19 @@ describe "Git HTTP requests (Geo)" do
end end
end end
describe 'POST upload_pack' do describe 'POST git_upload_pack' do
def make_request def make_request
post "/#{project.full_path}.git/git-upload-pack", {}, env post "/#{project.full_path}.git/git-upload-pack", {}, env
end end
it_behaves_like 'Geo sync request' it_behaves_like 'Geo request'
context 'when terms are enforced' do context 'when terms are enforced' do
before do before do
enforce_terms enforce_terms
end end
it_behaves_like 'Geo sync request' it_behaves_like 'Geo request'
end end
end end
...@@ -243,6 +257,112 @@ describe "Git HTTP requests (Geo)" do ...@@ -243,6 +257,112 @@ describe "Git HTTP requests (Geo)" do
end end
end end
end end
end
context 'when current node is the primary' do
let(:current_node) { primary }
describe 'POST git_receive_pack' do
def make_request
post url, {}, env
end
let(:url) { "/#{project.full_path}.git/git-receive-pack" }
before do
env['Geo-GL-Id'] = geo_gl_id
end
subject do
make_request
response
end
context 'when gl_id is not correctly provided via HTTP headers' do
context "as it's empty" do
where(:geo_gl_id) do
[
nil,
''
]
end
with_them do
it 'returns a 403' do
is_expected.to have_gitlab_http_status(:forbidden)
expect(response.body).to eql('You are not allowed to push code to this project.')
end
end
end
context "as it's junk" do
where(:geo_gl_id) do
[
'junk',
'junk-1',
'kkey-1'
]
end
with_them do
it 'returns a 403' do
is_expected.to have_gitlab_http_status(:forbidden)
expect(response.body).to eql('Geo push user is invalid.')
end
end
end
end
context 'when gl_id is provided via HTTP headers' do
context 'but is invalid' do
where(:geo_gl_id) do
[
'key-999',
'key-1',
'key-999'
]
end
with_them do
it 'returns a 403' do
is_expected.to have_gitlab_http_status(:forbidden)
expect(response.body).to eql('Geo push user is invalid.')
end
end
end
context 'and is valid' do
context 'but the user has no access' do
let(:geo_gl_id) { "key-#{key_for_user_without_any_access.id}" }
it 'returns a 404' do
is_expected.to have_gitlab_http_status(:not_found)
expect(response.body).to eql('The project you were looking for could not be found.')
end
end
context 'but the user does not have push access' do
let(:geo_gl_id) { "key-#{key_for_user_without_push_access.id}" }
it 'returns a 403' do
is_expected.to have_gitlab_http_status(:forbidden)
expect(response.body).to eql('You are not allowed to push code to this project.')
end
end
context 'and the user has push access' do
let(:geo_gl_id) { "key-#{key.id}" }
it 'returns a 200' do
is_expected.to have_gitlab_http_status(:ok)
expect(json_response['GL_ID']).to match("user-#{user.id}")
expect(json_response['GL_REPOSITORY']).to match(Gitlab::GlRepository.gl_repository(project, false))
end
end
end
end
end
end
def valid_geo_env def valid_geo_env
geo_env(auth_token) geo_env(auth_token)
......
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