From ac6412d0766fbc090a3aa8272cfd4cc2d9a26c16 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 15 Sep 2016 23:27:01 +0200 Subject: [PATCH] Added builds_spec and git_http_specs --- .../projects/git_http_client_controller.rb | 2 +- spec/requests/ci/api/builds_spec.rb | 77 ++++++++++++++++--- spec/requests/git_http_spec.rb | 69 +++++++++++++++-- spec/requests/jwt_controller_spec.rb | 2 +- 4 files changed, 130 insertions(+), 20 deletions(-) diff --git a/app/controllers/projects/git_http_client_controller.rb b/app/controllers/projects/git_http_client_controller.rb index 14e83ddda04..d92d28b7e02 100644 --- a/app/controllers/projects/git_http_client_controller.rb +++ b/app/controllers/projects/git_http_client_controller.rb @@ -117,7 +117,7 @@ class Projects::GitHttpClientController < Projects::ApplicationController case auth_result.type when :ci - if download_request? + if auth_result.project == project && download_request? @ci = true else return false diff --git a/spec/requests/ci/api/builds_spec.rb b/spec/requests/ci/api/builds_spec.rb index 780bd7f2859..09d72fe0a0e 100644 --- a/spec/requests/ci/api/builds_spec.rb +++ b/spec/requests/ci/api/builds_spec.rb @@ -254,7 +254,8 @@ describe Ci::API::API do let(:get_url) { ci_api("/builds/#{build.id}/artifacts") } let(:jwt_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') } let(:headers) { { "GitLab-Workhorse" => "1.0", Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => jwt_token } } - let(:headers_with_token) { headers.merge(Ci::API::Helpers::BUILD_TOKEN_HEADER => build.token) } + let(:token) { build.token } + let(:headers_with_token) { headers.merge(Ci::API::Helpers::BUILD_TOKEN_HEADER => token) } before { build.run! } @@ -274,6 +275,13 @@ describe Ci::API::API do expect(json_response["TempPath"]).not_to be_nil end + it "using runners token" do + post authorize_url, { token: build.project.runners_token }, headers + expect(response).to have_http_status(200) + expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) + expect(json_response["TempPath"]).not_to be_nil + end + it "reject requests that did not go through gitlab-workhorse" do headers.delete(Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER) post authorize_url, { token: build.token }, headers @@ -358,6 +366,16 @@ describe Ci::API::API do it_behaves_like 'successful artifacts upload' end + + context 'when using runners token' do + let(:token) { build.project.runners_token } + + before do + upload_artifacts(file_upload, headers_with_token) + end + + it_behaves_like 'successful artifacts upload' + end end context 'posts artifacts file and metadata file' do @@ -497,19 +515,40 @@ describe Ci::API::API do before do delete delete_url, token: build.token - build.reload end - it 'removes build artifacts' do - expect(response).to have_http_status(200) - expect(build.artifacts_file.exists?).to be_falsy - expect(build.artifacts_metadata.exists?).to be_falsy - expect(build.artifacts_size).to be_nil + shared_examples 'having removable artifacts' do + it 'removes build artifacts' do + build.reload + + expect(response).to have_http_status(200) + expect(build.artifacts_file.exists?).to be_falsy + expect(build.artifacts_metadata.exists?).to be_falsy + expect(build.artifacts_size).to be_nil + end + end + + context 'when using build token' do + before do + delete delete_url, token: build.token + end + + it_behaves_like 'having removable artifacts' + end + + context 'when using runnners token' do + before do + delete delete_url, token: build.project.runners_token + end + + it_behaves_like 'having removable artifacts' end end describe 'GET /builds/:id/artifacts' do - before { get get_url, token: build.token } + before do + get get_url, token: token + end context 'build has artifacts' do let(:build) { create(:ci_build, :artifacts) } @@ -518,13 +557,29 @@ describe Ci::API::API do 'Content-Disposition' => 'attachment; filename=ci_build_artifacts.zip' } end - it 'downloads artifact' do - expect(response).to have_http_status(200) - expect(response.headers).to include download_headers + shared_examples 'having downloadable artifacts' do + it 'download artifacts' do + expect(response).to have_http_status(200) + expect(response.headers).to include download_headers + end + end + + context 'when using build token' do + let(:token) { build.token } + + it_behaves_like 'having downloadable artifacts' + end + + context 'when using runnners token' do + let(:token) { build.project.runners_token } + + it_behaves_like 'having downloadable artifacts' end end context 'build does not has artifacts' do + let(:token) { build.token } + it 'responds with not found' do expect(response).to have_http_status(404) end diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb index 5977ee04524..0311755dd06 100644 --- a/spec/requests/git_http_spec.rb +++ b/spec/requests/git_http_spec.rb @@ -302,22 +302,77 @@ describe 'Git HTTP requests', lib: true do context "when a gitlab ci token is provided" do let(:build) { create(:ci_build, :running) } let(:project) { build.project } + let(:other_project) { create(:empty_project) } before do project.project_feature.update_attributes(builds_access_level: ProjectFeature::ENABLED) end - it "downloads get status 200" do - clone_get "#{project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token + context 'when build created by system is authenticated' do + it "downloads get status 200" do + clone_get "#{project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token - expect(response).to have_http_status(200) - expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) + expect(response).to have_http_status(200) + expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) + end + + it "uploads get status 401 (no project existence information leak)" do + push_get "#{project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token + + expect(response).to have_http_status(401) + end + + it "downloads from other project get status 401" do + clone_get "#{other_project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token + + expect(response).to have_http_status(401) + end end - it "uploads get status 401 (no project existence information leak)" do - push_get "#{project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token + context 'and build created by' do + before do + build.update(user: user) + project.team << [user, :reporter] + end - expect(response).to have_http_status(401) + shared_examples 'can download code only from own projects' do + it 'downloads get status 200' do + clone_get "#{project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token + + expect(response).to have_http_status(200) + expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) + end + + it 'uploads get status 403' do + push_get "#{project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token + + expect(response).to have_http_status(403) + end + end + + context 'administrator' do + let(:user) { create(:admin) } + + it_behaves_like 'can download code only from own projects' + + it 'downloads from other project get status 403' do + clone_get "#{other_project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token + + expect(response).to have_http_status(403) + end + end + + context 'regular user' do + let(:user) { create(:user) } + + it_behaves_like 'can download code only from own projects' + + it 'downloads from other project get status 404' do + clone_get "#{other_project.path_with_namespace}.git", user: 'gitlab-ci-token', password: build.token + + expect(response).to have_http_status(404) + end + end end end end diff --git a/spec/requests/jwt_controller_spec.rb b/spec/requests/jwt_controller_spec.rb index 1ca4541dbde..6b956e63004 100644 --- a/spec/requests/jwt_controller_spec.rb +++ b/spec/requests/jwt_controller_spec.rb @@ -45,7 +45,7 @@ describe JwtController do context 'using User login' do let(:user) { create(:user) } - let(:headers) { { authorization: credentials(user.username , user.password) } } + let(:headers) { { authorization: credentials(user.username, user.password) } } subject! { get '/jwt/auth', parameters, headers }