summaryrefslogtreecommitdiff
path: root/spec/requests/lfs_http_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/requests/lfs_http_spec.rb')
-rw-r--r--spec/requests/lfs_http_spec.rb256
1 files changed, 232 insertions, 24 deletions
diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb
index fcd6521317a..b58d410b7a3 100644
--- a/spec/requests/lfs_http_spec.rb
+++ b/spec/requests/lfs_http_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe 'Git LFS API and storage' do
+ include WorkhorseHelpers
+
let(:user) { create(:user) }
let!(:lfs_object) { create(:lfs_object, :with_file) }
@@ -12,6 +14,7 @@ describe 'Git LFS API and storage' do
end
let(:authorization) { }
let(:sendfile) { }
+ let(:pipeline) { create(:ci_empty_pipeline, project: project) }
let(:sample_oid) { lfs_object.oid }
let(:sample_size) { lfs_object.size }
@@ -242,14 +245,63 @@ describe 'Git LFS API and storage' do
end
end
- context 'when CI is authorized' do
+ context 'when build is authorized as' do
let(:authorization) { authorize_ci_project }
- let(:update_permissions) do
- project.lfs_objects << lfs_object
+ shared_examples 'can download LFS only from own projects' do
+ context 'for own project' do
+ let(:pipeline) { create(:ci_empty_pipeline, project: project) }
+
+ let(:update_permissions) do
+ project.team << [user, :reporter]
+ project.lfs_objects << lfs_object
+ end
+
+ it_behaves_like 'responds with a file'
+ end
+
+ context 'for other project' do
+ let(:other_project) { create(:empty_project) }
+ let(:pipeline) { create(:ci_empty_pipeline, project: other_project) }
+
+ let(:update_permissions) do
+ project.lfs_objects << lfs_object
+ end
+
+ it 'rejects downloading code' do
+ expect(response).to have_http_status(other_project_status)
+ end
+ end
+ end
+
+ context 'administrator' do
+ let(:user) { create(:admin) }
+ let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) }
+
+ it_behaves_like 'can download LFS only from own projects' do
+ # We render 403, because administrator does have normally access
+ let(:other_project_status) { 403 }
+ end
+ end
+
+ context 'regular user' do
+ let(:user) { create(:user) }
+ let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) }
+
+ it_behaves_like 'can download LFS only from own projects' do
+ # We render 404, to prevent data leakage about existence of the project
+ let(:other_project_status) { 404 }
+ end
end
- it_behaves_like 'responds with a file'
+ context 'does not have user' do
+ let(:build) { create(:ci_build, :running, pipeline: pipeline) }
+
+ it_behaves_like 'can download LFS only from own projects' do
+ # We render 404, to prevent data leakage about existence of the project
+ let(:other_project_status) { 404 }
+ end
+ end
end
end
@@ -429,10 +481,62 @@ describe 'Git LFS API and storage' do
end
end
- context 'when CI is authorized' do
+ context 'when build is authorized as' do
let(:authorization) { authorize_ci_project }
- it_behaves_like 'an authorized requests'
+ let(:update_lfs_permissions) do
+ project.lfs_objects << lfs_object
+ end
+
+ shared_examples 'can download LFS only from own projects' do
+ context 'for own project' do
+ let(:pipeline) { create(:ci_empty_pipeline, project: project) }
+
+ let(:update_user_permissions) do
+ project.team << [user, :reporter]
+ end
+
+ it_behaves_like 'an authorized requests'
+ end
+
+ context 'for other project' do
+ let(:other_project) { create(:empty_project) }
+ let(:pipeline) { create(:ci_empty_pipeline, project: other_project) }
+
+ it 'rejects downloading code' do
+ expect(response).to have_http_status(other_project_status)
+ end
+ end
+ end
+
+ context 'administrator' do
+ let(:user) { create(:admin) }
+ let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) }
+
+ it_behaves_like 'can download LFS only from own projects' do
+ # We render 403, because administrator does have normally access
+ let(:other_project_status) { 403 }
+ end
+ end
+
+ context 'regular user' do
+ let(:user) { create(:user) }
+ let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) }
+
+ it_behaves_like 'can download LFS only from own projects' do
+ # We render 404, to prevent data leakage about existence of the project
+ let(:other_project_status) { 404 }
+ end
+ end
+
+ context 'does not have user' do
+ let(:build) { create(:ci_build, :running, pipeline: pipeline) }
+
+ it_behaves_like 'can download LFS only from own projects' do
+ # We render 404, to prevent data leakage about existence of the project
+ let(:other_project_status) { 404 }
+ end
+ end
end
context 'when user is not authenticated' do
@@ -581,11 +685,37 @@ describe 'Git LFS API and storage' do
end
end
- context 'when CI is authorized' do
+ context 'when build is authorized' do
let(:authorization) { authorize_ci_project }
- it 'responds with 401' do
- expect(response).to have_http_status(401)
+ context 'build has an user' do
+ let(:user) { create(:user) }
+
+ context 'tries to push to own project' do
+ let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) }
+
+ it 'responds with 401' do
+ expect(response).to have_http_status(401)
+ end
+ end
+
+ context 'tries to push to other project' do
+ let(:other_project) { create(:empty_project) }
+ let(:pipeline) { create(:ci_empty_pipeline, project: other_project) }
+ let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) }
+
+ it 'responds with 401' do
+ expect(response).to have_http_status(401)
+ end
+ end
+ end
+
+ context 'does not have user' do
+ let(:build) { create(:ci_build, :running, pipeline: pipeline) }
+
+ it 'responds with 401' do
+ expect(response).to have_http_status(401)
+ end
end
end
end
@@ -607,14 +737,6 @@ describe 'Git LFS API and storage' do
end
end
end
-
- context 'when CI is authorized' do
- let(:authorization) { authorize_ci_project }
-
- it 'responds with status 403' do
- expect(response).to have_http_status(401)
- end
- end
end
describe 'unsupported' do
@@ -715,6 +837,12 @@ describe 'Git LFS API and storage' do
project.team << [user, :developer]
end
+ context 'and the request bypassed workhorse' do
+ it 'raises an exception' do
+ expect { put_authorize(verified: false) }.to raise_error JWT::DecodeError
+ end
+ end
+
context 'and request is sent by gitlab-workhorse to authorize the request' do
before do
put_authorize
@@ -724,6 +852,10 @@ describe 'Git LFS API and storage' do
expect(response).to have_http_status(200)
end
+ it 'uses the gitlab-workhorse content type' do
+ expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE)
+ end
+
it 'responds with status 200, location of lfs store and object details' do
expect(json_response['StoreLFSPath']).to eq("#{Gitlab.config.shared.path}/lfs-objects/tmp/upload")
expect(json_response['LfsOid']).to eq(sample_oid)
@@ -767,10 +899,51 @@ describe 'Git LFS API and storage' do
end
end
- context 'when CI is authenticated' do
+ context 'when build is authorized' do
let(:authorization) { authorize_ci_project }
- it_behaves_like 'unauthorized'
+ context 'build has an user' do
+ let(:user) { create(:user) }
+
+ context 'tries to push to own project' do
+ let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) }
+
+ before do
+ project.team << [user, :developer]
+ put_authorize
+ end
+
+ it 'responds with 401' do
+ expect(response).to have_http_status(401)
+ end
+ end
+
+ context 'tries to push to other project' do
+ let(:other_project) { create(:empty_project) }
+ let(:pipeline) { create(:ci_empty_pipeline, project: other_project) }
+ let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) }
+
+ before do
+ put_authorize
+ end
+
+ it 'responds with 401' do
+ expect(response).to have_http_status(401)
+ end
+ end
+ end
+
+ context 'does not have user' do
+ let(:build) { create(:ci_build, :running, pipeline: pipeline) }
+
+ before do
+ put_authorize
+ end
+
+ it 'responds with 401' do
+ expect(response).to have_http_status(401)
+ end
+ end
end
context 'for unauthenticated' do
@@ -827,10 +1000,42 @@ describe 'Git LFS API and storage' do
end
end
- context 'when CI is authenticated' do
+ context 'when build is authorized' do
let(:authorization) { authorize_ci_project }
- it_behaves_like 'unauthorized'
+ before do
+ put_authorize
+ end
+
+ context 'build has an user' do
+ let(:user) { create(:user) }
+
+ context 'tries to push to own project' do
+ let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) }
+
+ it 'responds with 401' do
+ expect(response).to have_http_status(401)
+ end
+ end
+
+ context 'tries to push to other project' do
+ let(:other_project) { create(:empty_project) }
+ let(:pipeline) { create(:ci_empty_pipeline, project: other_project) }
+ let(:build) { create(:ci_build, :running, pipeline: pipeline, user: user) }
+
+ it 'responds with 401' do
+ expect(response).to have_http_status(401)
+ end
+ end
+ end
+
+ context 'does not have user' do
+ let(:build) { create(:ci_build, :running, pipeline: pipeline) }
+
+ it 'responds with 401' do
+ expect(response).to have_http_status(401)
+ end
+ end
end
context 'for unauthenticated' do
@@ -863,8 +1068,11 @@ describe 'Git LFS API and storage' do
end
end
- def put_authorize
- put "#{project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}/#{sample_size}/authorize", nil, headers
+ def put_authorize(verified: true)
+ authorize_headers = headers
+ authorize_headers.merge!(workhorse_internal_api_request_header) if verified
+
+ put "#{project.http_url_to_repo}/gitlab-lfs/objects/#{sample_oid}/#{sample_size}/authorize", nil, authorize_headers
end
def put_finalize(lfs_tmp = lfs_tmp_file)
@@ -882,7 +1090,7 @@ describe 'Git LFS API and storage' do
end
def authorize_ci_project
- ActionController::HttpAuthentication::Basic.encode_credentials('gitlab-ci-token', project.runners_token)
+ ActionController::HttpAuthentication::Basic.encode_credentials('gitlab-ci-token', build.token)
end
def authorize_user