Commit 03da73d6 authored by Vitali Tatarintev's avatar Vitali Tatarintev

Merge branch '207448_remove_vulnerability_findings_finder' into 'master'

Remove vulnerability findings finder

See merge request gitlab-org/gitlab!39087
parents 5853f04f 44a31d8b
# frozen_string_literal: true
# Security::VulnerabilityFindingsFinder
#
# Used to filter Vulnerabilities::Findings by set of params for Security Dashboard
#
# Arguments:
# pipeline_ids - IDs for the pipelines to fetch vulnerabilities for
# params:
# severity: Array<String>
# confidence: Array<String>
# project: Array<String>
# report_type: Array<String>
# scope: String
module Security
class VulnerabilityFindingsFinder
attr_accessor :params
attr_reader :include_sha, :pipeline_ids
def initialize(pipeline_ids, params: {}, include_sha: false)
@pipeline_ids = pipeline_ids
@params = params
@include_sha = include_sha
end
def execute
collection = init_collection
collection = by_report_type(collection)
collection = by_project(collection)
collection = by_severity(collection)
collection = by_confidence(collection)
collection = by_scope(collection)
collection
end
private
def by_report_type(items)
return items unless params[:report_type].present?
items.by_report_types(
Vulnerabilities::Finding::REPORT_TYPES.values_at(
*params[:report_type]).compact)
end
def by_project(items)
return items unless params[:project_id].present?
items.by_projects(params[:project_id])
end
def by_severity(items)
return items unless params[:severity].present?
items.by_severities(
Vulnerabilities::Finding::SEVERITY_LEVELS.values_at(
*params[:severity]).compact)
end
def by_confidence(items)
return items unless params[:confidence].present?
items.by_confidences(
Vulnerabilities::Finding::CONFIDENCE_LEVELS.values_at(
*params[:confidence]).compact)
end
def by_scope(items)
# We're using the same params as the public Vulnerabilities API because the frontend uses both
# https://gitlab.com/gitlab-org/gitlab/issues/33468 fixes issue with param name meaning
return items if params[:scope] == 'all'
items.undismissed
end
def init_collection
if include_sha
::Vulnerabilities::Finding.for_pipelines_with_sha(pipeline_ids)
else
::Vulnerabilities::Finding.for_pipelines(pipeline_ids)
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Security::VulnerabilityFindingsFinder do
describe '#execute' do
let_it_be(:project1) { create(:project, :private, :repository) }
let_it_be(:project2) { create(:project, :private, :repository) }
let_it_be(:pipeline1) { create(:ci_pipeline, :success, project: project1) }
let_it_be(:pipeline2) { create(:ci_pipeline, :success, project: project2) }
let(:pipelines) { [pipeline1, pipeline2] }
let_it_be(:finding1) { create(:vulnerabilities_occurrence, report_type: :sast, severity: :high, confidence: :high, pipelines: [pipeline1], project: project1) }
let_it_be(:finding2) { create(:vulnerabilities_occurrence, report_type: :dependency_scanning, severity: :medium, confidence: :low, pipelines: [pipeline2], project: project2) }
let_it_be(:finding3) { create(:vulnerabilities_occurrence, report_type: :sast, severity: :low, pipelines: [pipeline2], project: project2) }
let_it_be(:finding4) { create(:vulnerabilities_occurrence, report_type: :dast, severity: :medium, pipelines: [pipeline1], project: project1) }
let(:params) { {} }
let(:include_sha) { false }
subject { described_class.new(pipelines, params: params, include_sha: include_sha).execute }
context 'when given a pipeline' do
let(:pipelines) { [pipeline1] }
it "returns vulnerability findings found in the pipeline" do
is_expected.to contain_exactly(finding1, finding4)
end
end
context 'include_sha' do
context 'when false' do
it 'does not include a sha' do
expect(subject.map(&:sha)).to be_all(&:nil?)
end
end
context 'when true' do
let(:include_sha) { true }
it 'includes the sha for the latest pipeline associated with the finding' do
subject.each do |finding|
expect(finding.sha).to eq(finding.pipelines.last.sha)
end
end
end
end
context 'by report type' do
context 'when sast' do
let(:params) { { report_type: %w[sast] } }
it 'includes only sast' do
is_expected.to contain_exactly(finding1, finding3)
end
end
context 'when dependency_scanning' do
let(:params) { { report_type: %w[dependency_scanning] } }
it 'includes only depscan' do
is_expected.to contain_exactly(finding2)
end
end
end
context 'by severity' do
context 'when high' do
let(:params) { { severity: %w[high] } }
it 'includes only high' do
is_expected.to contain_exactly(finding1)
end
end
context 'when medium' do
let(:params) { { severity: %w[medium] } }
it 'includes only medium' do
is_expected.to contain_exactly(finding2, finding4)
end
end
end
context 'by confidence' do
context 'when high' do
let(:params) { { confidence: %w[high] } }
it 'includes only high confidence vulnerabilities' do
is_expected.to contain_exactly(finding1)
end
end
context 'when low' do
let(:params) { { confidence: %w[low] } }
it 'includes only low confidence vulnerabilities' do
is_expected.to contain_exactly(finding2)
end
end
end
context 'by project' do
let(:params) { { project_id: [project2.id] } }
it 'includes only vulnerabilities for one project' do
is_expected.to contain_exactly(finding2, finding3)
end
end
context 'by all filters' do
context 'with found entity' do
let(:params) { { severity: %w[high medium low], project_id: [project1.id, project2.id], report_type: %w[sast dast], scope: 'all' } }
before do
create(:vulnerability_feedback, :sast, :dismissal,
pipeline: pipeline1,
project: project1,
project_fingerprint: finding1.project_fingerprint)
end
it 'filters by all params' do
is_expected.to contain_exactly(finding1, finding3, finding4)
end
end
context 'without found entity' do
let(:params) { { severity: %w[low], project_id: [project1.id], report_type: %w[sast] } }
it 'did not find anything' do
is_expected.to be_empty
end
end
end
context 'by scope' do
let!(:dismissal) do
create(:vulnerability_feedback, :sast, :dismissal,
pipeline: pipeline1,
project: project1,
project_fingerprint: finding1.project_fingerprint)
end
let!(:issue) do
create(:vulnerability_feedback, :sast, :issue,
pipeline: pipeline1,
project: project1,
project_fingerprint: finding4.project_fingerprint)
end
context 'when all' do
let(:params) { { scope: 'all' } }
it 'includes all vulnerabilities' do
is_expected.to contain_exactly(finding1, finding2, finding3, finding4)
end
end
context 'when not specified' do
let(:params) { {} }
it 'excludes dismissed vulnerabilities' do
is_expected.to contain_exactly(finding2, finding3, finding4)
end
end
context 'when dismissed' do
let(:params) { { scope: 'dismissed' } }
it 'excludes dismissed vulnerabilities' do
is_expected.to contain_exactly(finding2, finding3, finding4)
end
end
end
context 'by some filters' do
context 'with found entity' do
let(:params) { { project_id: [project2.id], severity: %w[medium low] } }
it 'filters by all params' do
is_expected.to contain_exactly(finding2, finding3)
end
end
context 'without found entity' do
let(:params) { { project_id: project1.id, severity: %w[low] } }
it 'did not find anything' do
is_expected.to be_empty
end
end
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment