Commit 321c1bc5 authored by Alan (Maciej) Paruszewski's avatar Alan (Maciej) Paruszewski Committed by Stan Hu

Resolve issue with showing Pipeline Occurrences without scanner

This change fixes NoMethodError exception when Pipeline Security tab was
presented with no or broken scanner section.
parent 6047bf27
...@@ -89,7 +89,7 @@ module Security ...@@ -89,7 +89,7 @@ module Security
occurrence.vulnerability = vulnerabilities[occurrence.project_fingerprint] occurrence.vulnerability = vulnerabilities[occurrence.project_fingerprint]
occurrence.project = pipeline.project occurrence.project = pipeline.project
occurrence.sha = pipeline.sha occurrence.sha = pipeline.sha
occurrence.build_scanner(report_occurrence.scanner.to_hash) occurrence.build_scanner(report_occurrence.scanner&.to_hash)
occurrence.identifiers = report_occurrence.identifiers.map do |identifier| occurrence.identifiers = report_occurrence.identifiers.map do |identifier|
Vulnerabilities::Identifier.new(identifier.to_hash) Vulnerabilities::Identifier.new(identifier.to_hash)
end end
......
...@@ -54,6 +54,8 @@ module Security ...@@ -54,6 +54,8 @@ module Security
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
def create_or_find_vulnerability_finding(occurrence, create_params) def create_or_find_vulnerability_finding(occurrence, create_params)
return if occurrence.scanner.blank?
find_params = { find_params = {
scanner: scanners_objects[occurrence.scanner.key], scanner: scanners_objects[occurrence.scanner.key],
primary_identifier: identifiers_objects[occurrence.primary_identifier.key], primary_identifier: identifiers_objects[occurrence.primary_identifier.key],
...@@ -73,6 +75,8 @@ module Security ...@@ -73,6 +75,8 @@ module Security
end end
def update_vulnerability_scanner(occurrence) def update_vulnerability_scanner(occurrence)
return if occurrence.scanner.blank?
scanner = scanners_objects[occurrence.scanner.key] scanner = scanners_objects[occurrence.scanner.key]
scanner.update!(occurrence.scanner.to_hash) scanner.update!(occurrence.scanner.to_hash)
end end
...@@ -105,7 +109,7 @@ module Security ...@@ -105,7 +109,7 @@ module Security
def scanners_objects def scanners_objects
strong_memoize(:scanners_objects) do strong_memoize(:scanners_objects) do
@report.scanners.map do |key, scanner| @report.scanners.map do |key, scanner|
[key, existing_scanner_objects[key] || project.vulnerability_scanners.build(scanner.to_hash)] [key, existing_scanner_objects[key] || project.vulnerability_scanners.build(scanner&.to_hash)]
end.to_h end.to_h
end end
end end
......
---
title: Display occurrences in Pipeline Security view when scanner information is missing
merge_request: 35795
author:
type: fixed
...@@ -169,6 +169,16 @@ FactoryBot.define do ...@@ -169,6 +169,16 @@ FactoryBot.define do
end end
end end
trait :sast_with_missing_scanner do
file_type { :sast }
file_format { :raw }
after(:build) do |artifact, _|
artifact.file = fixture_file_upload(
Rails.root.join('ee/spec/fixtures/security_reports/master/gl-sast-missing-scanner.json'), 'application/json')
end
end
trait :license_management do trait :license_management do
to_create { |instance| instance.save(validate: false) } to_create { |instance| instance.save(validate: false) }
......
...@@ -10,7 +10,7 @@ RSpec.describe Security::PipelineVulnerabilitiesFinder do ...@@ -10,7 +10,7 @@ RSpec.describe Security::PipelineVulnerabilitiesFinder do
end end
let_it_be(:project) { create(:project, :repository) } let_it_be(:project) { create(:project, :repository) }
let_it_be(:pipeline) { create(:ci_pipeline, :success, project: project) } let_it_be(:pipeline, reload: true) { create(:ci_pipeline, :success, project: project) }
describe '#execute' do describe '#execute' do
let(:params) { {} } let(:params) { {} }
...@@ -23,7 +23,7 @@ RSpec.describe Security::PipelineVulnerabilitiesFinder do ...@@ -23,7 +23,7 @@ RSpec.describe Security::PipelineVulnerabilitiesFinder do
let_it_be(:artifact_cs) { create(:ee_ci_job_artifact, :container_scanning, job: build_cs, project: project) } let_it_be(:artifact_cs) { create(:ee_ci_job_artifact, :container_scanning, job: build_cs, project: project) }
let_it_be(:artifact_dast) { create(:ee_ci_job_artifact, :dast, job: build_dast, project: project) } let_it_be(:artifact_dast) { create(:ee_ci_job_artifact, :dast, job: build_dast, project: project) }
let_it_be(:artifact_ds) { create(:ee_ci_job_artifact, :dependency_scanning, job: build_ds, project: project) } let_it_be(:artifact_ds) { create(:ee_ci_job_artifact, :dependency_scanning, job: build_ds, project: project) }
let_it_be(:artifact_sast) { create(:ee_ci_job_artifact, :sast, job: build_sast, project: project) } let!(:artifact_sast) { create(:ee_ci_job_artifact, :sast, job: build_sast, project: project) }
let(:cs_count) { read_fixture(artifact_cs)['vulnerabilities'].count } let(:cs_count) { read_fixture(artifact_cs)['vulnerabilities'].count }
let(:ds_count) { read_fixture(artifact_ds)['vulnerabilities'].count } let(:ds_count) { read_fixture(artifact_ds)['vulnerabilities'].count }
...@@ -299,6 +299,16 @@ RSpec.describe Security::PipelineVulnerabilitiesFinder do ...@@ -299,6 +299,16 @@ RSpec.describe Security::PipelineVulnerabilitiesFinder do
end end
end end
context 'when scanner is not provided in the report occurrences' do
let!(:artifact_sast) { create(:ee_ci_job_artifact, :sast_with_missing_scanner, job: build_sast, project: project) }
it 'sets empty scanner' do
sast_scanners = subject.occurrences.select(&:sast?).map(&:scanner)
expect(sast_scanners).to all(have_attributes(project_id: nil, external_id: nil, name: nil))
end
end
def read_fixture(fixture) def read_fixture(fixture)
Gitlab::Json.parse(File.read(fixture.file.path)) Gitlab::Json.parse(File.read(fixture.file.path))
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