summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomasz Maczukin <tomasz@maczukin.pl>2017-02-28 14:27:25 +0100
committerTomasz Maczukin <tomasz@maczukin.pl>2017-03-02 17:45:46 +0100
commit2a7f555caf8588ad78f054f29e740a2a4a30deb3 (patch)
treeb929b08b1adc7fdb9f8666a2f980495a8a32a293
parent7e46db0f5a5b6aa84ac653fa4826b70bf50d6909 (diff)
downloadgitlab-ce-2a7f555caf8588ad78f054f29e740a2a4a30deb3.tar.gz
Add artifacts uploading authorize API
-rw-r--r--lib/api/helpers/runner.rb4
-rw-r--r--lib/api/runner.rb30
-rw-r--r--spec/requests/api/runner_spec.rb77
3 files changed, 111 insertions, 0 deletions
diff --git a/lib/api/helpers/runner.rb b/lib/api/helpers/runner.rb
index e71895c091e..97255cc8c81 100644
--- a/lib/api/helpers/runner.rb
+++ b/lib/api/helpers/runner.rb
@@ -68,6 +68,10 @@ module API
token = (params[JOB_TOKEN_PARAM] || env[JOB_TOKEN_HEADER]).to_s
token && job.valid_token?(token)
end
+
+ def max_artifacts_size
+ current_application_settings.max_artifacts_size.megabytes.to_i
+ end
end
end
end
diff --git a/lib/api/runner.rb b/lib/api/runner.rb
index 2b636847dba..54105988f36 100644
--- a/lib/api/runner.rb
+++ b/lib/api/runner.rb
@@ -144,6 +144,36 @@ module API
header 'Job-Status', job.status
header 'Range', "0-#{job.trace_length}"
end
+
+ desc 'Authorize artifacts uploading for job' do
+ http_codes [[200, 'Upload allowed'],
+ [403, 'Forbidden'],
+ [405, 'Artifacts support not enabled'],
+ [413, 'File too large']]
+ end
+ params do
+ requires :id, type: Fixnum, desc: %q(Job's ID)
+ optional :token, type: String, desc: %q(Job's authentication token)
+ optional :filesize, type: Fixnum, desc: %q(ARtifacts filesize)
+ end
+ post '/:id/artifacts/authorize' do
+ not_allowed! unless Gitlab.config.artifacts.enabled
+ require_gitlab_workhorse!
+ Gitlab::Workhorse.verify_api_request!(headers)
+
+ job = Ci::Build.find_by_id(params[:id])
+ authenticate_job!(job)
+ forbidden!('Job is not running') unless job.running?
+
+ if params[:filesize]
+ file_size = params[:filesize].to_i
+ file_to_large! unless file_size < max_artifacts_size
+ end
+
+ status 200
+ content_type Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE
+ Gitlab::Workhorse.artifact_upload_ok
+ end
end
end
end
diff --git a/spec/requests/api/runner_spec.rb b/spec/requests/api/runner_spec.rb
index c5844810cdd..1625da6e449 100644
--- a/spec/requests/api/runner_spec.rb
+++ b/spec/requests/api/runner_spec.rb
@@ -614,5 +614,82 @@ describe API::Runner do
2.times { patch_the_trace('') }
end
end
+
+ describe 'artifacts' do
+ 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(API::Helpers::Runner::JOB_TOKEN_HEADER => job.token) }
+
+ before { job.run! }
+
+ describe 'POST /api/v4/jobs/:id/artifacts/authorize' do
+ context 'when using token as parameter' do
+ it 'authorizes posting artifacts to running job' do
+ authorize_artifacts_with_token_in_params
+
+ 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 'fails to post too large artifact' do
+ stub_application_setting(max_artifacts_size: 0)
+ authorize_artifacts_with_token_in_params(filesize: 100)
+
+ expect(response).to have_http_status(413)
+ end
+ end
+
+ context 'when using token as header' do
+ it 'authorizes posting artifacts to running job' do
+ authorize_artifacts_with_token_in_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 'fails to post too large artifact' do
+ stub_application_setting(max_artifacts_size: 0)
+ authorize_artifacts_with_token_in_headers(filesize: 100)
+
+ expect(response).to have_http_status(413)
+ end
+ end
+
+ context 'when using runners token' do
+ it 'fails to authorize artifacts posting' do
+ authorize_artifacts(token: job.project.runners_token)
+ expect(response).to have_http_status(403)
+ end
+ end
+
+ it 'reject requests that did not go through gitlab-workhorse' do
+ headers.delete(Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER)
+ authorize_artifacts
+ expect(response).to have_http_status(500)
+ end
+
+ context 'authorization token is invalid' do
+ it 'responds with forbidden' do
+ authorize_artifacts(token: 'invalid', filesize: 100 )
+ expect(response).to have_http_status(403)
+ end
+ end
+
+ def authorize_artifacts(params = {}, request_headers = headers)
+ post api("/jobs/#{job.id}/artifacts/authorize"), params, request_headers
+ end
+
+ def authorize_artifacts_with_token_in_params(params = {}, request_headers = headers)
+ params = params.merge(token: job.token)
+ authorize_artifacts(params, request_headers)
+ end
+
+ def authorize_artifacts_with_token_in_headers(params = {}, request_headers = headers_with_token)
+ authorize_artifacts(params, request_headers)
+ end
+ end
+ end
end
end