diff options
Diffstat (limited to 'lib/api/ci')
-rw-r--r-- | lib/api/ci/job_artifacts.rb | 72 | ||||
-rw-r--r-- | lib/api/ci/jobs.rb | 17 | ||||
-rw-r--r-- | lib/api/ci/runner.rb | 14 | ||||
-rw-r--r-- | lib/api/ci/runners.rb | 10 | ||||
-rw-r--r-- | lib/api/ci/secure_files.rb | 47 |
5 files changed, 116 insertions, 44 deletions
diff --git a/lib/api/ci/job_artifacts.rb b/lib/api/ci/job_artifacts.rb index 352ad04c982..3788f5bec41 100644 --- a/lib/api/ci/job_artifacts.rb +++ b/lib/api/ci/job_artifacts.rb @@ -16,18 +16,25 @@ module API end end - prepend_mod_with('API::Ci::JobArtifacts') # rubocop: disable Cop/InjectEnterpriseEditionModule - params do requires :id, types: [String, Integer], desc: 'The ID or URL-encoded path of the project' end resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do desc 'Download the artifacts archive from a job' do detail 'This feature was introduced in GitLab 8.10' + failure [ + { code: 401, message: 'Unauthorized' }, + { code: 403, message: 'Forbidden' }, + { code: 404, message: 'Not found' } + ] end params do - requires :ref_name, type: String, desc: 'The ref from repository' - requires :job, type: String, desc: 'The name for the job' + requires :ref_name, type: String, + desc: 'Branch or tag name in repository. `HEAD` or `SHA` references are not supported.' + requires :job, type: String, desc: 'The name of the job.' + optional :job_token, type: String, + desc: 'To be used with triggers for multi-project pipelines, ' \ + 'available only on Premium and Ultimate tiers.' end route_setting :authentication, job_token_allowed: true get ':id/jobs/artifacts/:ref_name/download', @@ -43,11 +50,21 @@ module API desc 'Download a specific file from artifacts archive from a ref' do detail 'This feature was introduced in GitLab 11.5' + failure [ + { code: 400, message: 'Bad request' }, + { code: 401, message: 'Unauthorized' }, + { code: 403, message: 'Forbidden' }, + { code: 404, message: 'Not found' } + ] end params do - requires :ref_name, type: String, desc: 'The ref from repository' - requires :job, type: String, desc: 'The name for the job' - requires :artifact_path, type: String, desc: 'Artifact path' + requires :ref_name, type: String, + desc: 'Branch or tag name in repository. `HEAD` or `SHA` references are not supported.' + requires :job, type: String, desc: 'The name of the job.' + requires :artifact_path, type: String, desc: 'Path to a file inside the artifacts archive.' + optional :job_token, type: String, + desc: 'To be used with triggers for multi-project pipelines, ' \ + 'available only on Premium and Ultimate tiers.' end route_setting :authentication, job_token_allowed: true get ':id/jobs/artifacts/:ref_name/raw/*artifact_path', @@ -69,9 +86,17 @@ module API desc 'Download the artifacts archive from a job' do detail 'This feature was introduced in GitLab 8.5' + failure [ + { code: 401, message: 'Unauthorized' }, + { code: 403, message: 'Forbidden' }, + { code: 404, message: 'Not found' } + ] end params do requires :job_id, type: Integer, desc: 'The ID of a job' + optional :job_token, type: String, + desc: 'To be used with triggers for multi-project pipelines, ' \ + 'available only on Premium and Ultimate tiers.' end route_setting :authentication, job_token_allowed: true get ':id/jobs/:job_id/artifacts', urgency: :low do @@ -85,10 +110,19 @@ module API desc 'Download a specific file from artifacts archive' do detail 'This feature was introduced in GitLab 10.0' + failure [ + { code: 400, message: 'Bad request' }, + { code: 401, message: 'Unauthorized' }, + { code: 403, message: 'Forbidden' }, + { code: 404, message: 'Not found' } + ] end params do requires :job_id, type: Integer, desc: 'The ID of a job' - requires :artifact_path, type: String, desc: 'Artifact path' + requires :artifact_path, type: String, desc: 'Path to a file inside the artifacts archive.' + optional :job_token, type: String, + desc: 'To be used with triggers for multi-project pipelines, ' \ + 'available only on Premium and Ultimate tiers.' end route_setting :authentication, job_token_allowed: true get ':id/jobs/:job_id/artifacts/*artifact_path', urgency: :low, format: false do @@ -113,6 +147,11 @@ module API desc 'Keep the artifacts to prevent them from being deleted' do success ::API::Entities::Ci::Job + failure [ + { code: 401, message: 'Unauthorized' }, + { code: 403, message: 'Forbidden' }, + { code: 404, message: 'Not found' } + ] end params do requires :job_id, type: Integer, desc: 'The ID of a job' @@ -132,6 +171,12 @@ module API desc 'Delete the artifacts files from a job' do detail 'This feature was introduced in GitLab 11.9' + success code: 204 + failure [ + { code: 401, message: 'Unauthorized' }, + { code: 403, message: 'Forbidden' }, + { code: 409, message: 'Conflict' } + ] end params do requires :job_id, type: Integer, desc: 'The ID of a job' @@ -148,7 +193,14 @@ module API status :no_content end - desc 'Expire the artifacts files from a project' + desc 'Expire the artifacts files from a project' do + success code: 202 + failure [ + { code: 401, message: 'Unauthorized' }, + { code: 403, message: 'Forbidden' }, + { code: 409, message: 'Conflict' } + ] + end delete ':id/artifacts' do authorize_destroy_artifacts! @@ -162,3 +214,5 @@ module API end end end + +API::Ci::JobArtifacts.prepend_mod diff --git a/lib/api/ci/jobs.rb b/lib/api/ci/jobs.rb index 9e41e1c0d8f..bb57a717f7c 100644 --- a/lib/api/ci/jobs.rb +++ b/lib/api/ci/jobs.rb @@ -49,13 +49,15 @@ module API end # rubocop: disable CodeReuse/ActiveRecord get ':id/jobs', urgency: :low, feature_category: :continuous_integration do + check_rate_limit!(:jobs_index, scope: current_user) if enforce_jobs_api_rate_limits(@project) + authorize_read_builds! builds = user_project.builds.order('id DESC') builds = filter_builds(builds, params[:scope]) - builds = builds.preload(:user, :job_artifacts_archive, :job_artifacts, :runner, :tags, pipeline: :project) - present paginate(builds), with: Entities::Ci::Job + + present paginate(builds, without_count: true), with: Entities::Ci::Job end # rubocop: enable CodeReuse/ActiveRecord @@ -255,16 +257,19 @@ module API pipeline = current_authenticated_job.pipeline project = current_authenticated_job.project - agent_authorizations = ::Clusters::AgentAuthorizationsFinder.new(project).execute project_groups = project.group&.self_and_ancestor_ids&.map { |id| { id: id } } || [] user_access_level = project.team.max_member_access(current_user.id) roles_in_project = Gitlab::Access.sym_options_with_owner .select { |_role, role_access_level| role_access_level <= user_access_level } .map(&:first) - environment = if persisted_environment = current_authenticated_job.actual_persisted_environment - { tier: persisted_environment.tier, slug: persisted_environment.slug } - end + persisted_environment = current_authenticated_job.actual_persisted_environment + environment = { tier: persisted_environment.tier, slug: persisted_environment.slug } if persisted_environment + + agent_authorizations = ::Clusters::Agents::FilterAuthorizationsService.new( + ::Clusters::AgentAuthorizationsFinder.new(project).execute, + environment: persisted_environment&.name + ).execute # See https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/kubernetes_ci_access.md#apiv4joballowed_agents-api { diff --git a/lib/api/ci/runner.rb b/lib/api/ci/runner.rb index c7d1887638a..b073eb49bf1 100644 --- a/lib/api/ci/runner.rb +++ b/lib/api/ci/runner.rb @@ -229,15 +229,17 @@ module API params do requires :id, type: Integer, desc: %q(Job's ID) optional :token, type: String, desc: %q(Job's authentication token) + optional :debug_trace, type: Boolean, desc: %q(Enable or Disable the debug trace) end patch '/:id/trace', urgency: :low, feature_category: :continuous_integration do job = authenticate_job!(heartbeat_runner: true) error!('400 Missing header Content-Range', 400) unless request.headers.key?('Content-Range') content_range = request.headers['Content-Range'] + debug_trace = Gitlab::Utils.to_boolean(params[:debug_trace]) result = ::Ci::AppendBuildTraceService - .new(job, content_range: content_range) + .new(job, content_range: content_range, debug_trace: debug_trace) .execute(request.body.read) if result.status == 403 @@ -256,7 +258,7 @@ module API header 'X-GitLab-Trace-Update-Interval', job.trace.update_interval.to_s end - desc 'Authorize artifacts uploading for job' do + desc 'Authorize uploading job artifact' do http_codes [[200, 'Upload allowed'], [403, 'Forbidden'], [405, 'Artifacts support not enabled'], @@ -270,7 +272,7 @@ module API # In current runner, filesize parameter would be empty here. This is because archive is streamed by runner, # so the archive size is not known ahead of time. Streaming is done to not use additional I/O on # Runner to first save, and then send via Network. - optional :filesize, type: Integer, desc: %q(Artifacts filesize) + optional :filesize, type: Integer, desc: %q(Size of artifact file) optional :artifact_type, type: String, desc: %q(The type of artifact), default: 'archive', values: ::Ci::JobArtifact.file_types.keys @@ -292,7 +294,7 @@ module API end end - desc 'Upload artifacts for job' do + desc 'Upload a job artifact' do success Entities::Ci::JobRequest::Response http_codes [[201, 'Artifact uploaded'], [400, 'Bad request'], @@ -304,7 +306,7 @@ module API requires :id, type: Integer, desc: %q(Job's ID) requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: %(The artifact file to store (generated by Multipart middleware)), documentation: { type: 'file' } optional :token, type: String, desc: %q(Job's authentication token) - optional :expire_in, type: String, desc: %q(Specify when artifacts should expire) + optional :expire_in, type: String, desc: %q(Specify when artifact should expire) optional :artifact_type, type: String, desc: %q(The type of artifact), default: 'archive', values: ::Ci::JobArtifact.file_types.keys optional :artifact_format, type: String, desc: %q(The format of artifact), @@ -333,7 +335,7 @@ module API end desc 'Download the artifacts file for job' do - http_codes [[200, 'Upload allowed'], + http_codes [[200, 'Download allowed'], [401, 'Unauthorized'], [403, 'Forbidden'], [404, 'Artifact not found']] diff --git a/lib/api/ci/runners.rb b/lib/api/ci/runners.rb index 988c3f4f566..4a6c58b4987 100644 --- a/lib/api/ci/runners.rb +++ b/lib/api/ci/runners.rb @@ -58,19 +58,19 @@ module API end def authenticate_show_runner!(runner) - return if runner.instance_type? || current_user.admin? + return if runner.instance_type? || current_user.can_read_all_resources? forbidden!("No access granted") unless can?(current_user, :read_runner, runner) end def authenticate_update_runner!(runner) - return if current_user.admin? + return if current_user.can_admin_all_resources? forbidden!("No access granted") unless can?(current_user, :update_runner, runner) end def authenticate_delete_runner!(runner) - return if current_user.admin? + return if current_user.can_admin_all_resources? forbidden!("Runner associated with more than one project") if runner.runner_projects.count > 1 forbidden!("No access granted") unless can?(current_user, :delete_runner, runner) @@ -79,14 +79,14 @@ module API def authenticate_enable_runner!(runner) forbidden!("Runner is a group runner") if runner.group_type? - return if current_user.admin? + return if current_user.can_admin_all_resources? forbidden!("Runner is locked") if runner.locked? forbidden!("No access granted") unless can?(current_user, :assign_runner, runner) end def authenticate_list_runners_jobs!(runner) - return if current_user.admin? + return if current_user.can_read_all_resources? forbidden!("No access granted") unless can?(current_user, :read_builds, runner) end diff --git a/lib/api/ci/secure_files.rb b/lib/api/ci/secure_files.rb index dd628a3413f..6483abcc74e 100644 --- a/lib/api/ci/secure_files.rb +++ b/lib/api/ci/secure_files.rb @@ -7,7 +7,6 @@ module API before do authenticate! - feature_flag_enabled? authorize! :read_secure_files, user_project end @@ -16,11 +15,15 @@ module API default_format :json params do - requires :id, types: [String, Integer], desc: 'The ID or URL-encoded path of the project' + requires :id, types: [String, Integer], desc: 'The ID or URL-encoded path of the project owned by the + authenticated user' end resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do - desc 'List all Secure Files for a Project' + desc 'Get list of secure files in a project' do + success Entities::Ci::SecureFile + tags %w[secure_files] + end params do use :pagination end @@ -30,9 +33,13 @@ module API present paginate(secure_files), with: Entities::Ci::SecureFile end - desc 'Get an individual Secure File' + desc 'Get the details of a specific secure file in a project' do + success Entities::Ci::SecureFile + tags %w[secure_files] + failure [{ code: 404, message: '404 Not found' }] + end params do - requires :id, type: Integer, desc: 'The Secure File ID' + requires :id, type: Integer, desc: 'The ID of a secure file' end route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: true @@ -41,7 +48,10 @@ module API present secure_file, with: Entities::Ci::SecureFile end - desc 'Download a Secure File' + desc 'Download secure file' do + failure [{ code: 404, message: '404 Not found' }] + tags %w[secure_files] + end route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: true get ':id/secure_files/:secure_file_id/download' do secure_file = user_project.secure_files.find(params[:secure_file_id]) @@ -58,10 +68,15 @@ module API authorize! :admin_secure_files, user_project end - desc 'Upload a Secure File' + desc 'Create a secure file' do + success Entities::Ci::SecureFile + tags %w[secure_files] + failure [{ code: 400, message: '400 Bad Request' }] + end params do - requires :name, type: String, desc: 'The name of the file' - requires :file, types: [Rack::Multipart::UploadedFile, ::API::Validations::Types::WorkhorseFile], desc: 'The secure file to be uploaded', documentation: { type: 'file' } + requires :name, type: String, desc: 'The name of the file being uploaded. The filename must be unique within + the project' + requires :file, types: [Rack::Multipart::UploadedFile, ::API::Validations::Types::WorkhorseFile], desc: 'The secure file being uploaded', documentation: { type: 'file' } end route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: true post ':id/secure_files' do @@ -74,17 +89,17 @@ module API file_too_large! unless secure_file.file.size < ::Ci::SecureFile::FILE_SIZE_LIMIT.to_i if secure_file.save - if Feature.enabled?(:secure_files_metadata_parsers, user_project) - ::Ci::ParseSecureFileMetadataWorker.perform_async(secure_file.id) # rubocop:disable CodeReuse/Worker - end - + ::Ci::ParseSecureFileMetadataWorker.perform_async(secure_file.id) # rubocop:disable CodeReuse/Worker present secure_file, with: Entities::Ci::SecureFile else render_validation_error!(secure_file) end end - desc 'Delete an individual Secure File' + desc 'Remove a secure file' do + tags %w[secure_files] + failure [{ code: 404, message: '404 Not found' }] + end route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: true delete ':id/secure_files/:secure_file_id' do secure_file = user_project.secure_files.find(params[:secure_file_id]) @@ -97,10 +112,6 @@ module API end helpers do - def feature_flag_enabled? - service_unavailable! unless Feature.enabled?(:ci_secure_files, user_project) - end - def read_only_feature_flag_enabled? service_unavailable! if Feature.enabled?(:ci_secure_files_read_only, user_project, type: :ops) end |