Add artifacts uploading authorize API
This commit is contained in:
		
							parent
							
								
									7e46db0f5a
								
							
						
					
					
						commit
						2a7f555caf
					
				|  | @ -68,6 +68,10 @@ module API | ||||||
|         token = (params[JOB_TOKEN_PARAM] || env[JOB_TOKEN_HEADER]).to_s |         token = (params[JOB_TOKEN_PARAM] || env[JOB_TOKEN_HEADER]).to_s | ||||||
|         token && job.valid_token?(token) |         token && job.valid_token?(token) | ||||||
|       end |       end | ||||||
|  | 
 | ||||||
|  |       def max_artifacts_size | ||||||
|  |         current_application_settings.max_artifacts_size.megabytes.to_i | ||||||
|  |       end | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -144,6 +144,36 @@ module API | ||||||
|         header 'Job-Status', job.status |         header 'Job-Status', job.status | ||||||
|         header 'Range', "0-#{job.trace_length}" |         header 'Range', "0-#{job.trace_length}" | ||||||
|       end |       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 |   end | ||||||
| end | end | ||||||
|  |  | ||||||
|  | @ -614,5 +614,82 @@ describe API::Runner do | ||||||
|         2.times { patch_the_trace('') } |         2.times { patch_the_trace('') } | ||||||
|       end |       end | ||||||
|     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 | ||||||
| end | end | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue