diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-01-11 21:10:43 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-01-11 21:10:43 +0300 |
commit | dcacb5daf7941dd2be05e6f688027baae92a6c81 (patch) | |
tree | 58e1a4b5be95bbc15f60c7c31a9709668ea1cb18 /lib | |
parent | ec971a05e380fa580ae75dea30ab963112096525 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'lib')
-rw-r--r-- | lib/expand_variables.rb | 6 | ||||
-rw-r--r-- | lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback.rb | 128 | ||||
-rw-r--r-- | lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml | 45 | ||||
-rw-r--r-- | lib/gitlab/ci/variables/collection/sorted.rb | 77 | ||||
-rw-r--r-- | lib/gitlab/git_access_snippet.rb | 14 | ||||
-rw-r--r-- | lib/gitlab/gon_helper.rb | 4 | ||||
-rw-r--r-- | lib/gitlab/quick_actions/merge_request_actions.rb | 5 |
7 files changed, 270 insertions, 9 deletions
diff --git a/lib/expand_variables.rb b/lib/expand_variables.rb index dc8f9d0c970..06cebab8f0a 100644 --- a/lib/expand_variables.rb +++ b/lib/expand_variables.rb @@ -16,6 +16,12 @@ module ExpandVariables end end + def possible_var_reference?(value) + return unless value + + %w[$ %].any? { |symbol| value.include?(symbol) } + end + private def replace_with(value, variables) diff --git a/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback.rb b/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback.rb new file mode 100644 index 00000000000..52b09e07fd5 --- /dev/null +++ b/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback.rb @@ -0,0 +1,128 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + # This class populates the `finding_uuid` attribute for + # the existing `vulnerability_feedback` records. + class PopulateFindingUuidForVulnerabilityFeedback + REPORT_TYPES = { + sast: 0, + dependency_scanning: 1, + container_scanning: 2, + dast: 3, + secret_detection: 4, + coverage_fuzzing: 5, + api_fuzzing: 6 + }.freeze + + class VulnerabilityFeedback < ActiveRecord::Base # rubocop:disable Style/Documentation + include EachBatch + + self.table_name = 'vulnerability_feedback' + + enum category: REPORT_TYPES + + scope :in_range, -> (start, stop) { where(id: start..stop) } + scope :without_uuid, -> { where(finding_uuid: nil) } + + def self.load_vulnerability_findings + all.to_a.tap { |collection| collection.each(&:vulnerability_finding) } + end + + def set_finding_uuid + return unless vulnerability_finding.present? && vulnerability_finding.primary_identifier.present? + + update_column(:finding_uuid, calculated_uuid) + rescue StandardError => error + Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error) + end + + def vulnerability_finding + BatchLoader.for(finding_key).batch(replace_methods: false) do |finding_keys, loader| + project_ids = finding_keys.map { |key| key[:project_id] } + categories = finding_keys.map { |key| key[:category] } + fingerprints = finding_keys.map { |key| key[:project_fingerprint] } + + findings = Finding.with_primary_identifier.where( + project_id: project_ids.uniq, + report_type: categories.uniq, + project_fingerprint: fingerprints.uniq + ).to_a + + finding_keys.each do |finding_key| + loader.call( + finding_key, + findings.find { |f| finding_key == f.finding_key } + ) + end + end + end + + private + + def calculated_uuid + Gitlab::UUID.v5(uuid_components) + end + + def uuid_components + [ + category, + vulnerability_finding.primary_identifier.fingerprint, + vulnerability_finding.location_fingerprint, + project_id + ].join('-') + end + + def finding_key + { + project_id: project_id, + category: category, + project_fingerprint: project_fingerprint + } + end + end + + class Finding < ActiveRecord::Base # rubocop:disable Style/Documentation + include ShaAttribute + + self.table_name = 'vulnerability_occurrences' + + sha_attribute :project_fingerprint + sha_attribute :location_fingerprint + + belongs_to :primary_identifier, class_name: 'Gitlab::BackgroundMigration::PopulateFindingUuidForVulnerabilityFeedback::Identifier' + + enum report_type: REPORT_TYPES + + scope :with_primary_identifier, -> { includes(:primary_identifier) } + + def finding_key + { + project_id: project_id, + category: report_type, + project_fingerprint: project_fingerprint + } + end + end + + class Identifier < ActiveRecord::Base # rubocop:disable Style/Documentation + self.table_name = 'vulnerability_identifiers' + end + + def perform(*range) + feedback = VulnerabilityFeedback.without_uuid.in_range(*range).load_vulnerability_findings + feedback.each(&:set_finding_uuid) + + log_info(feedback.count) + end + + def log_info(feedback_count) + ::Gitlab::BackgroundMigration::Logger.info( + migrator: self.class.name, + message: '`finding_uuid` attributes has been set', + count: feedback_count + ) + end + end + end +end diff --git a/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml new file mode 100644 index 00000000000..dc3e1ab5ef8 --- /dev/null +++ b/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml @@ -0,0 +1,45 @@ +# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/dast/ + +# Configure the scanning tool through the environment variables. +# List of the variables: https://docs.gitlab.com/ee/user/application_security/dast/#available-variables +# How to set: https://docs.gitlab.com/ee/ci/yaml/#variables + +variables: + DAST_VERSION: 1 + # Setting this variable will affect all Security templates + # (SAST, Dependency Scanning, ...) + SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers" + +dast: + stage: dast + image: + name: "$SECURE_ANALYZERS_PREFIX/dast:$DAST_VERSION" + variables: + GIT_STRATEGY: none + allow_failure: true + script: + - export DAST_WEBSITE=${DAST_WEBSITE:-$(cat environment_url.txt)} + - if [ -z "$DAST_WEBSITE$DAST_API_SPECIFICATION" ]; then echo "Either DAST_WEBSITE or DAST_API_SPECIFICATION must be set. See https://docs.gitlab.com/ee/user/application_security/dast/#configuration for more details." && exit 1; fi + - /analyze + artifacts: + reports: + dast: gl-dast-report.json + rules: + - if: $DAST_DISABLED + when: never + - if: $DAST_DISABLED_FOR_DEFAULT_BRANCH && + $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME + when: never + - if: $CI_DEFAULT_BRANCH != $CI_COMMIT_REF_NAME && + $REVIEW_DISABLED && $DAST_WEBSITE == null && + $DAST_API_SPECIFICATION == null + when: never + - if: $CI_COMMIT_BRANCH && + $CI_KUBERNETES_ACTIVE && + $GITLAB_FEATURES =~ /\bdast\b/ + - if: $CI_COMMIT_BRANCH && + $GITLAB_FEATURES =~ /\bdast\b/ && + $DAST_WEBSITE + - if: $CI_COMMIT_BRANCH && + $GITLAB_FEATURES =~ /\bdast\b/ && + $DAST_API_SPECIFICATION diff --git a/lib/gitlab/ci/variables/collection/sorted.rb b/lib/gitlab/ci/variables/collection/sorted.rb new file mode 100644 index 00000000000..6abc6a5644f --- /dev/null +++ b/lib/gitlab/ci/variables/collection/sorted.rb @@ -0,0 +1,77 @@ +# frozen_string_literal: true + +module Gitlab + module Ci + module Variables + class Collection + class Sorted + include TSort + include Gitlab::Utils::StrongMemoize + + def initialize(variables) + @variables = variables + end + + def valid? + errors.nil? + end + + # errors sorts an array of variables, ignoring unknown variable references, + # and returning an error string if a circular variable reference is found + def errors + return if Feature.disabled?(:variable_inside_variable) + + strong_memoize(:errors) do + # Check for cyclic dependencies and build error message in that case + errors = each_strongly_connected_component.filter_map do |component| + component.map { |v| v[:key] }.inspect if component.size > 1 + end + + "circular variable reference detected: #{errors.join(', ')}" if errors.any? + end + end + + # sort sorts an array of variables, ignoring unknown variable references. + # If a circular variable reference is found, the original array is returned + def sort + return @variables if Feature.disabled?(:variable_inside_variable) + return @variables if errors + + tsort + end + + private + + def tsort_each_node(&block) + @variables.each(&block) + end + + def tsort_each_child(variable, &block) + each_variable_reference(variable[:value], &block) + end + + def input_vars + strong_memoize(:input_vars) do + @variables.index_by { |env| env.fetch(:key) } + end + end + + def walk_references(value) + return unless ExpandVariables.possible_var_reference?(value) + + value.scan(ExpandVariables::VARIABLES_REGEXP) do |var_ref| + yield(input_vars, var_ref.first) + end + end + + def each_variable_reference(value) + walk_references(value) do |vars_hash, ref_var_name| + variable = vars_hash.dig(ref_var_name) + yield variable if variable + end + end + end + end + end + end +end diff --git a/lib/gitlab/git_access_snippet.rb b/lib/gitlab/git_access_snippet.rb index 482881daca6..88a75f72840 100644 --- a/lib/gitlab/git_access_snippet.rb +++ b/lib/gitlab/git_access_snippet.rb @@ -59,7 +59,7 @@ module Gitlab # TODO: Investigate if expanding actor/authentication types are needed. # https://gitlab.com/gitlab-org/gitlab/issues/202190 if actor && !allowed_actor? - raise ForbiddenError, ERROR_MESSAGES[:authentication_mechanism] + raise ForbiddenError, error_message(:authentication_mechanism) end super @@ -71,14 +71,18 @@ module Gitlab override :check_push_access! def check_push_access! - raise ForbiddenError, ERROR_MESSAGES[:update_snippet] unless user + raise ForbiddenError, error_message(:update_snippet) unless user + + if snippet&.repository_read_only? + raise ForbiddenError, error_message(:read_only) + end check_change_access! end def check_snippet_accessibility! if snippet.blank? - raise NotFoundError, ERROR_MESSAGES[:snippet_not_found] + raise NotFoundError, error_message(:snippet_not_found) end end @@ -94,14 +98,14 @@ module Gitlab passed = guest_can_download_code? || user_can_download_code? unless passed - raise ForbiddenError, ERROR_MESSAGES[:read_snippet] + raise ForbiddenError, error_message(:read_snippet) end end override :check_change_access! def check_change_access! unless user_can_push? - raise ForbiddenError, ERROR_MESSAGES[:update_snippet] + raise ForbiddenError, error_message(:update_snippet) end check_size_before_push! diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb index 10e8f00874d..0ba535b500e 100644 --- a/lib/gitlab/gon_helper.rb +++ b/lib/gitlab/gon_helper.rb @@ -4,7 +4,6 @@ module Gitlab module GonHelper - include StartupCssHelper include WebpackHelper def add_gon_variables @@ -49,9 +48,6 @@ module Gitlab push_frontend_feature_flag(:usage_data_api, default_enabled: true) push_frontend_feature_flag(:security_auto_fix, default_enabled: false) push_frontend_feature_flag(:gl_tooltips, default_enabled: :yaml) - - # Startup CSS feature is a special one as it can be enabled by means of cookies and params - gon.push({ features: { 'startupCss' => use_startup_css? } }, true) end # Exposes the state of a feature flag to the frontend code. diff --git a/lib/gitlab/quick_actions/merge_request_actions.rb b/lib/gitlab/quick_actions/merge_request_actions.rb index 70c581c6454..31cc3f930c0 100644 --- a/lib/gitlab/quick_actions/merge_request_actions.rb +++ b/lib/gitlab/quick_actions/merge_request_actions.rb @@ -57,6 +57,11 @@ module Gitlab access_check.can_push_to_branch?(merge_request.source_branch) end command :rebase do + if quick_action_target.cannot_be_merged? + @execution_message[:rebase] = _('This merge request cannot be rebased while there are conflicts.') + next + end + if quick_action_target.rebase_in_progress? @execution_message[:rebase] = _('A rebase is already in progress.') next |