diff options
author | Tomasz Maczukin <tomasz@maczukin.pl> | 2017-02-28 14:27:25 +0100 |
---|---|---|
committer | Tomasz Maczukin <tomasz@maczukin.pl> | 2017-03-02 17:45:46 +0100 |
commit | 2a7f555caf8588ad78f054f29e740a2a4a30deb3 (patch) | |
tree | b929b08b1adc7fdb9f8666a2f980495a8a32a293 | |
parent | 7e46db0f5a5b6aa84ac653fa4826b70bf50d6909 (diff) | |
download | gitlab-ce-2a7f555caf8588ad78f054f29e740a2a4a30deb3.tar.gz |
Add artifacts uploading authorize API
-rw-r--r-- | lib/api/helpers/runner.rb | 4 | ||||
-rw-r--r-- | lib/api/runner.rb | 30 | ||||
-rw-r--r-- | spec/requests/api/runner_spec.rb | 77 |
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 |