From 7a6c7bd66bae678640c98ad426cd0153f638b163 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 23 Feb 2018 10:33:46 +0000 Subject: [PATCH] Allow token authentication on go-get request --- changelogs/unreleased/dm-go-get-api-token.yml | 5 + lib/gitlab/auth/request_authenticator.rb | 8 ++ lib/gitlab/middleware/go.rb | 10 +- spec/lib/gitlab/middleware/go_spec.rb | 91 +++++++++++++++---- 4 files changed, 97 insertions(+), 17 deletions(-) create mode 100644 changelogs/unreleased/dm-go-get-api-token.yml diff --git a/changelogs/unreleased/dm-go-get-api-token.yml b/changelogs/unreleased/dm-go-get-api-token.yml new file mode 100644 index 00000000000..ad9cfe05849 --- /dev/null +++ b/changelogs/unreleased/dm-go-get-api-token.yml @@ -0,0 +1,5 @@ +--- +title: Allow token authentication on go-get request +merge_request: +author: +type: changed diff --git a/lib/gitlab/auth/request_authenticator.rb b/lib/gitlab/auth/request_authenticator.rb index 46ec040ce92..a0b5cd868c3 100644 --- a/lib/gitlab/auth/request_authenticator.rb +++ b/lib/gitlab/auth/request_authenticator.rb @@ -20,6 +20,14 @@ module Gitlab rescue Gitlab::Auth::AuthenticationError nil end + + def valid_access_token?(scopes: []) + validate_access_token!(scopes: scopes) + + true + rescue Gitlab::Auth::AuthenticationError + false + end end end end diff --git a/lib/gitlab/middleware/go.rb b/lib/gitlab/middleware/go.rb index 1a570f480c6..1fd8f147b44 100644 --- a/lib/gitlab/middleware/go.rb +++ b/lib/gitlab/middleware/go.rb @@ -114,7 +114,15 @@ module Gitlab end def current_user(request) - request.env['warden']&.authenticate + authenticator = Gitlab::Auth::RequestAuthenticator.new(request) + user = authenticator.find_user_from_access_token || authenticator.find_user_from_warden + + return unless user&.can?(:access_api) + + # Right now, the `api` scope is the only one that should be able to determine private project existence. + return unless authenticator.valid_access_token?(scopes: [:api]) + + user end end end diff --git a/spec/lib/gitlab/middleware/go_spec.rb b/spec/lib/gitlab/middleware/go_spec.rb index 60a134be939..b24c9882c0c 100644 --- a/spec/lib/gitlab/middleware/go_spec.rb +++ b/spec/lib/gitlab/middleware/go_spec.rb @@ -3,19 +3,30 @@ require 'spec_helper' describe Gitlab::Middleware::Go do let(:app) { double(:app) } let(:middleware) { described_class.new(app) } + let(:env) do + { + 'rack.input' => '', + 'REQUEST_METHOD' => 'GET' + } + end describe '#call' do describe 'when go-get=0' do + before do + env['QUERY_STRING'] = 'go-get=0' + end + it 'skips go-import generation' do - env = { 'rack.input' => '', - 'QUERY_STRING' => 'go-get=0' } expect(app).to receive(:call).with(env).and_return('no-go') middleware.call(env) end end describe 'when go-get=1' do - let(:current_user) { nil } + before do + env['QUERY_STRING'] = 'go-get=1' + env['PATH_INFO'] = "/#{path}" + end shared_examples 'go-get=1' do |enabled_protocol:| context 'with simple 2-segment project path' do @@ -54,21 +65,75 @@ describe Gitlab::Middleware::Go do project.update_attribute(:visibility_level, Project::PRIVATE) end - context 'with access to the project' do + shared_examples 'unauthorized' do + it 'returns the 2-segment group path' do + expect_response_with_path(go, enabled_protocol, group.full_path) + end + end + + context 'when not authenticated' do + it_behaves_like 'unauthorized' + end + + context 'when authenticated' do let(:current_user) { project.creator } before do project.team.add_master(current_user) end - it 'returns the full project path' do - expect_response_with_path(go, enabled_protocol, project.full_path) + shared_examples 'authenticated' do + context 'with access to the project' do + it 'returns the full project path' do + expect_response_with_path(go, enabled_protocol, project.full_path) + end + end + + context 'without access to the project' do + before do + project.team.find_member(current_user).destroy + end + + it_behaves_like 'unauthorized' + end end - end - context 'without access to the project' do - it 'returns the 2-segment group path' do - expect_response_with_path(go, enabled_protocol, group.full_path) + context 'using warden' do + before do + env['warden'] = double(authenticate: current_user) + end + + context 'when active' do + it_behaves_like 'authenticated' + end + + context 'when blocked' do + before do + current_user.block! + end + + it_behaves_like 'unauthorized' + end + end + + context 'using a personal access token' do + let(:personal_access_token) { create(:personal_access_token, user: current_user) } + + before do + env['HTTP_PRIVATE_TOKEN'] = personal_access_token.token + end + + context 'with api scope' do + it_behaves_like 'authenticated' + end + + context 'with read_user scope' do + before do + personal_access_token.update_attribute(:scopes, [:read_user]) + end + + it_behaves_like 'unauthorized' + end end end end @@ -138,12 +203,6 @@ describe Gitlab::Middleware::Go do end def go - env = { - 'rack.input' => '', - 'QUERY_STRING' => 'go-get=1', - 'PATH_INFO' => "/#{path}", - 'warden' => double(authenticate: current_user) - } middleware.call(env) end -- GitLab