diff options
Diffstat (limited to 'lib/gitlab/ci/pipeline/chain/validate/external.rb')
-rw-r--r-- | lib/gitlab/ci/pipeline/chain/validate/external.rb | 85 |
1 files changed, 65 insertions, 20 deletions
diff --git a/lib/gitlab/ci/pipeline/chain/validate/external.rb b/lib/gitlab/ci/pipeline/chain/validate/external.rb index d056501a6d3..6149d2f04d7 100644 --- a/lib/gitlab/ci/pipeline/chain/validate/external.rb +++ b/lib/gitlab/ci/pipeline/chain/validate/external.rb @@ -10,77 +10,116 @@ module Gitlab InvalidResponseCode = Class.new(StandardError) - VALIDATION_REQUEST_TIMEOUT = 5 + DEFAULT_VALIDATION_REQUEST_TIMEOUT = 5 + ACCEPTED_STATUS = 200 + DOT_COM_REJECTED_STATUS = 406 + GENERAL_REJECTED_STATUS = (400..499).freeze def perform! + return unless enabled? + pipeline_authorized = validate_external log_message = pipeline_authorized ? 'authorized' : 'not authorized' - Gitlab::AppLogger.info(message: "Pipeline #{log_message}", project_id: @pipeline.project.id, user_id: @pipeline.user.id) + Gitlab::AppLogger.info(message: "Pipeline #{log_message}", project_id: project.id, user_id: current_user.id) error('External validation failed', drop_reason: :external_validation_failure) unless pipeline_authorized end def break? - @pipeline.errors.any? + pipeline.errors.any? end private + def enabled? + return true unless Gitlab.com? + + ::Feature.enabled?(:ci_external_validation_service, project, default_enabled: :yaml) + end + def validate_external return true unless validation_service_url # 200 - accepted - # 4xx - not accepted + # 406 - not accepted on GitLab.com + # 4XX - not accepted for other installations # everything else - accepted and logged response_code = validate_service_request.code case response_code - when 200 + when ACCEPTED_STATUS true - when 400..499 + when rejected_status false else raise InvalidResponseCode, "Unsupported response code received from Validation Service: #{response_code}" end rescue => ex - Gitlab::ErrorTracking.track_exception(ex) + Gitlab::ErrorTracking.track_exception(ex, project_id: project.id) true end + def rejected_status + if Gitlab.com? + DOT_COM_REJECTED_STATUS + else + GENERAL_REJECTED_STATUS + end + end + def validate_service_request + headers = { + 'X-Gitlab-Correlation-id' => Labkit::Correlation::CorrelationId.current_id, + 'X-Gitlab-Token' => validation_service_token + }.compact + Gitlab::HTTP.post( - validation_service_url, timeout: VALIDATION_REQUEST_TIMEOUT, - body: validation_service_payload(@pipeline, @command.yaml_processor_result.stages_attributes) + validation_service_url, timeout: validation_service_timeout, + headers: headers, + body: validation_service_payload.to_json ) end + def validation_service_timeout + timeout = Gitlab::CurrentSettings.external_pipeline_validation_service_timeout || ENV['EXTERNAL_VALIDATION_SERVICE_TIMEOUT'].to_i + return timeout if timeout > 0 + + DEFAULT_VALIDATION_REQUEST_TIMEOUT + end + def validation_service_url - ENV['EXTERNAL_VALIDATION_SERVICE_URL'] + Gitlab::CurrentSettings.external_pipeline_validation_service_url || ENV['EXTERNAL_VALIDATION_SERVICE_URL'] + end + + def validation_service_token + Gitlab::CurrentSettings.external_pipeline_validation_service_token || ENV['EXTERNAL_VALIDATION_SERVICE_TOKEN'] end - def validation_service_payload(pipeline, stages_attributes) + def validation_service_payload { project: { - id: pipeline.project.id, - path: pipeline.project.full_path + id: project.id, + path: project.full_path, + created_at: project.created_at&.iso8601 }, user: { - id: pipeline.user.id, - username: pipeline.user.username, - email: pipeline.user.email + id: current_user.id, + username: current_user.username, + email: current_user.email, + created_at: current_user.created_at&.iso8601 }, pipeline: { sha: pipeline.sha, ref: pipeline.ref, type: pipeline.source }, - builds: builds_validation_payload(stages_attributes) - }.to_json + builds: builds_validation_payload + } end - def builds_validation_payload(stages_attributes) - stages_attributes.map { |stage| stage[:builds] }.flatten + def builds_validation_payload + stages_attributes.flat_map { |stage| stage[:builds] } .map(&method(:build_validation_payload)) end @@ -97,9 +136,15 @@ module Gitlab ].flatten.compact } end + + def stages_attributes + command.yaml_processor_result.stages_attributes + end end end end end end end + +Gitlab::Ci::Pipeline::Chain::Validate::External.prepend_if_ee('EE::Gitlab::Ci::Pipeline::Chain::Validate::External') |