Commit fe0d76d1 authored by Stan Hu's avatar Stan Hu

Merge branch 'fix_parsers_design_flaw' into 'master'

Fix parsers design flaw

See merge request gitlab-org/gitlab!50223
parents 5821a492 b11ed0e3
...@@ -164,7 +164,7 @@ module EE ...@@ -164,7 +164,7 @@ module EE
def parse_security_artifact_blob(security_report, blob) def parse_security_artifact_blob(security_report, blob)
report_clone = security_report.clone_as_blank report_clone = security_report.clone_as_blank
::Gitlab::Ci::Parsers.fabricate!(security_report.type).parse!(blob, report_clone) ::Gitlab::Ci::Parsers.fabricate!(security_report.type, blob, report_clone).parse!
security_report.merge!(report_clone) security_report.merge!(report_clone)
end end
......
...@@ -120,7 +120,7 @@ module EE ...@@ -120,7 +120,7 @@ module EE
report = ::Gitlab::Ci::Reports::Security::Report.new(file_type, job.pipeline, nil).tap do |report| report = ::Gitlab::Ci::Reports::Security::Report.new(file_type, job.pipeline, nil).tap do |report|
each_blob do |blob| each_blob do |blob|
::Gitlab::Ci::Parsers.fabricate!(file_type).parse!(blob, report) ::Gitlab::Ci::Parsers.fabricate!(file_type, blob, report).parse!
end end
end end
......
...@@ -7,16 +7,21 @@ module Gitlab ...@@ -7,16 +7,21 @@ module Gitlab
class Common class Common
SecurityReportParserError = Class.new(Gitlab::Ci::Parsers::ParserError) SecurityReportParserError = Class.new(Gitlab::Ci::Parsers::ParserError)
def parse!(json_data, report) def self.parse!(json_data, report)
report_data = parse_report(json_data) new(json_data, report).parse!
raise SecurityReportParserError, "Invalid report format" unless report_data.is_a?(Hash) end
create_scanner(report, report_data.dig('scan', 'scanner')) def initialize(json_data, report)
create_scan(report, report_data.dig('scan')) @json_data = json_data
@report = report
end
collate_remediations(report_data).each do |vulnerability| def parse!
create_vulnerability(report, vulnerability, report_data["version"]) raise SecurityReportParserError, "Invalid report format" unless report_data.is_a?(Hash)
end
create_scanner
create_scan
collate_remediations.each { |vulnerability| create_vulnerability(vulnerability) }
report_data report_data
rescue JSON::ParserError rescue JSON::ParserError
...@@ -26,25 +31,38 @@ module Gitlab ...@@ -26,25 +31,38 @@ module Gitlab
raise SecurityReportParserError, "#{report.type} security report parsing failed" raise SecurityReportParserError, "#{report.type} security report parsing failed"
end end
protected private
attr_reader :json_data, :report
def report_data
@report_data ||= Gitlab::Json.parse!(json_data)
end
def report_version
@report_version ||= report_data['version']
end
def top_level_scanner
@top_level_scanner ||= report_data.dig('scan', 'scanner')
end
def parse_report(json_data) def scan_data
Gitlab::Json.parse!(json_data) @scan_data ||= report_data.dig('scan')
end end
# map remediations to relevant vulnerabilities # map remediations to relevant vulnerabilities
def collate_remediations(report_data) def collate_remediations
return report_data["vulnerabilities"] || [] unless report_data["remediations"] return report_data["vulnerabilities"] || [] unless report_data["remediations"]
fixes = fixes_from(report_data)
report_data["vulnerabilities"].map do |vulnerability| report_data["vulnerabilities"].map do |vulnerability|
remediation = fixes[vulnerability['id']] || fixes[vulnerability['cve']] remediation = fixes[vulnerability['id']] || fixes[vulnerability['cve']]
vulnerability.merge("remediations" => [remediation]) vulnerability.merge("remediations" => [remediation])
end end
end end
def fixes_from(report_data) def fixes
report_data['remediations'].each_with_object({}) do |item, memo| @fixes ||= report_data['remediations'].each_with_object({}) do |item, memo|
item['fixes'].each do |fix| item['fixes'].each do |fix|
id = fix['id'] || fix['cve'] id = fix['id'] || fix['cve']
memo[id] = item if id memo[id] = item if id
...@@ -53,56 +71,54 @@ module Gitlab ...@@ -53,56 +71,54 @@ module Gitlab
end end
end end
def create_vulnerability(report, data, version) def create_vulnerability(data)
identifiers = create_identifiers(report, data['identifiers']) identifiers = create_identifiers(data['identifiers'])
links = create_links(report, data['links']) links = create_links(data['links'])
location = create_location(data['location'] || {}) location = create_location(data['location'] || {})
remediations = create_remediations(data['remediations']) remediations = create_remediations(data['remediations'])
report.add_finding( report.add_finding(
::Gitlab::Ci::Reports::Security::Finding.new( ::Gitlab::Ci::Reports::Security::Finding.new(
uuid: calculate_uuid_v5(report, location, identifiers.first), uuid: calculate_uuid_v5(identifiers.first, location),
report_type: report.type, report_type: report.type,
name: finding_name(data, identifiers, location), name: finding_name(data, identifiers, location),
compare_key: data['cve'] || '', compare_key: data['cve'] || '',
location: location, location: location,
severity: parse_severity_level(data['severity']&.downcase), severity: parse_severity_level(data['severity']),
confidence: parse_confidence_level(data['confidence']&.downcase), confidence: parse_confidence_level(data['confidence']),
scanner: create_scanner(report, data['scanner']), scanner: create_scanner(data['scanner']),
scan: report&.scan, scan: report&.scan,
identifiers: identifiers, identifiers: identifiers,
links: links, links: links,
remediations: remediations, remediations: remediations,
raw_metadata: data.to_json, raw_metadata: data.to_json,
metadata_version: version, metadata_version: report_version,
details: data['details'] || {})) details: data['details'] || {}))
end end
def create_scan(report, scan_data) def create_scan
return unless scan_data.is_a?(Hash) return unless scan_data.is_a?(Hash)
report.scan = ::Gitlab::Ci::Reports::Security::Scan.new(scan_data) report.scan = ::Gitlab::Ci::Reports::Security::Scan.new(scan_data)
end end
def create_scanner(report, scanner) def create_scanner(scanner_data = top_level_scanner)
return unless scanner.is_a?(Hash) return unless scanner_data.is_a?(Hash)
report.add_scanner( report.add_scanner(
::Gitlab::Ci::Reports::Security::Scanner.new( ::Gitlab::Ci::Reports::Security::Scanner.new(
external_id: scanner['id'], external_id: scanner_data['id'],
name: scanner['name'], name: scanner_data['name'],
vendor: scanner.dig('vendor', 'name'))) vendor: scanner_data.dig('vendor', 'name')))
end end
def create_identifiers(report, identifiers) def create_identifiers(identifiers)
return [] unless identifiers.is_a?(Array) return [] unless identifiers.is_a?(Array)
identifiers.map do |identifier| identifiers.map { |identifier| create_identifier(identifier) }.compact
create_identifier(report, identifier)
end.compact
end end
def create_identifier(report, identifier) def create_identifier(identifier)
return unless identifier.is_a?(Hash) return unless identifier.is_a?(Hash)
report.add_identifier( report.add_identifier(
...@@ -113,20 +129,16 @@ module Gitlab ...@@ -113,20 +129,16 @@ module Gitlab
url: identifier['url'])) url: identifier['url']))
end end
def create_links(report, links) def create_links(links)
return [] unless links.is_a?(Array) return [] unless links.is_a?(Array)
links links.map { |link| create_link(link) }.compact
.map { |link| create_link(report, link) }
.compact
end end
def create_link(report, link) def create_link(link)
return unless link.is_a?(Hash) return unless link.is_a?(Hash)
::Gitlab::Ci::Reports::Security::Link.new( ::Gitlab::Ci::Reports::Security::Link.new(name: link['name'], url: link['url'])
name: link['name'],
url: link['url'])
end end
def create_remediations(remediations_data) def create_remediations(remediations_data)
...@@ -136,23 +148,17 @@ module Gitlab ...@@ -136,23 +148,17 @@ module Gitlab
end end
def parse_severity_level(input) def parse_severity_level(input)
return input if ::Enums::Vulnerability.severity_levels.key?(input) input&.downcase.then { |value| ::Enums::Vulnerability.severity_levels.key?(value) ? value : 'unknown' }
'unknown'
end end
def parse_confidence_level(input) def parse_confidence_level(input)
return input if ::Enums::Vulnerability.confidence_levels.key?(input) input&.downcase.then { |value| ::Enums::Vulnerability.confidence_levels.key?(value) ? value : 'unknown' }
'unknown'
end end
def create_location(location_data) def create_location(location_data)
raise NotImplementedError raise NotImplementedError
end end
private
def finding_name(data, identifiers, location) def finding_name(data, identifiers, location)
return data['message'] if data['message'].present? return data['message'] if data['message'].present?
return data['name'] if data['name'].present? return data['name'] if data['name'].present?
...@@ -161,7 +167,7 @@ module Gitlab ...@@ -161,7 +167,7 @@ module Gitlab
"#{identifier.name} in #{location&.fingerprint_path}" "#{identifier.name} in #{location&.fingerprint_path}"
end end
def calculate_uuid_v5(report, location, primary_identifier) def calculate_uuid_v5(primary_identifier, location)
uuid_v5_name_components = { uuid_v5_name_components = {
report_type: report.type, report_type: report.type,
primary_identifier_fingerprint: primary_identifier&.fingerprint, primary_identifier_fingerprint: primary_identifier&.fingerprint,
......
...@@ -14,17 +14,19 @@ module Gitlab ...@@ -14,17 +14,19 @@ module Gitlab
override :parse_report override :parse_report
end end
def parse_report(json_data) def report_data
report = super @report_data ||= begin
data = super
if report.is_a?(Array) if data.is_a?(Array)
report = { data = {
"version" => self.class::DEPRECATED_REPORT_VERSION, "version" => self.class::DEPRECATED_REPORT_VERSION,
"vulnerabilities" => report "vulnerabilities" => data
} }
end end
report data
end
end end
end end
end end
......
...@@ -5,20 +5,20 @@ module Gitlab ...@@ -5,20 +5,20 @@ module Gitlab
module Parsers module Parsers
module Security module Security
class Dast < Common class Dast < Common
def parse!(json_data, report) def parse!
report_data = super super
report.scanned_resources = create_scanned_resources(report_data.dig('scan', 'scanned_resources')) report.scanned_resources = create_scanned_resources(report_data.dig('scan', 'scanned_resources'))
end end
private private
def parse_report(json_data) def report_data
report = super @report_data ||= begin
super.then do |data|
return Formatters::Dast.new(report).format if Formatters::Dast.satisfies?(report) Formatters::Dast.satisfies?(data) ? Formatters::Dast.new(data).format : data
end
report end
end end
def create_scanned_resources(scanned_resources) def create_scanned_resources(scanned_resources)
......
...@@ -56,10 +56,10 @@ RSpec.describe Security::FindingsFinder do ...@@ -56,10 +56,10 @@ RSpec.describe Security::FindingsFinder do
before(:all) do before(:all) do
ds_content = File.read(artifact_ds.file.path) ds_content = File.read(artifact_ds.file.path)
Gitlab::Ci::Parsers::Security::DependencyScanning.new.parse!(ds_content, report_ds) Gitlab::Ci::Parsers::Security::DependencyScanning.parse!(ds_content, report_ds)
report_ds.merge!(report_ds) report_ds.merge!(report_ds)
sast_content = File.read(artifact_sast.file.path) sast_content = File.read(artifact_sast.file.path)
Gitlab::Ci::Parsers::Security::Sast.new.parse!(sast_content, report_sast) Gitlab::Ci::Parsers::Security::Sast.parse!(sast_content, report_sast)
report_sast.merge!(report_sast) report_sast.merge!(report_sast)
{ artifact_ds => report_ds, artifact_sast => report_sast }.each do |artifact, report| { artifact_ds => report_ds, artifact_sast => report_sast }.each do |artifact, report|
......
...@@ -8,13 +8,14 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do ...@@ -8,13 +8,14 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
let(:artifact) { build(:ee_ci_job_artifact, :common_security_report) } let(:artifact) { build(:ee_ci_job_artifact, :common_security_report) }
let(:report) { Gitlab::Ci::Reports::Security::Report.new(artifact.file_type, pipeline, 2.weeks.ago) } let(:report) { Gitlab::Ci::Reports::Security::Report.new(artifact.file_type, pipeline, 2.weeks.ago) }
let(:parser) { described_class.new }
let(:location) { ::Gitlab::Ci::Reports::Security::Locations::DependencyScanning.new(file_path: 'yarn/yarn.lock', package_version: 'v2', package_name: 'saml2') } let(:location) { ::Gitlab::Ci::Reports::Security::Locations::DependencyScanning.new(file_path: 'yarn/yarn.lock', package_version: 'v2', package_name: 'saml2') }
before do before do
allow(parser).to receive(:create_location).and_return(location) allow_next_instance_of(described_class) do |parser|
allow(parser).to receive(:create_location).and_return(location)
end
artifact.each_blob { |blob| parser.parse!(blob, report) } artifact.each_blob { |blob| described_class.parse!(blob, report) }
end end
describe 'parsing finding.name' do describe 'parsing finding.name' do
...@@ -142,9 +143,8 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do ...@@ -142,9 +143,8 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
end end
it 'returns nil when scan is not a hash' do it 'returns nil when scan is not a hash' do
parser = described_class.new
empty_report = Gitlab::Ci::Reports::Security::Report.new(artifact.file_type, pipeline, 2.weeks.ago) empty_report = Gitlab::Ci::Reports::Security::Report.new(artifact.file_type, pipeline, 2.weeks.ago)
parser.parse!({}.to_json, empty_report) described_class.parse!({}.to_json, empty_report)
expect(empty_report.scan).to be(nil) expect(empty_report.scan).to be(nil)
end end
......
...@@ -3,15 +3,12 @@ ...@@ -3,15 +3,12 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::Ci::Parsers::Security::ContainerScanning do RSpec.describe Gitlab::Ci::Parsers::Security::ContainerScanning do
let(:parser) { described_class.new }
let(:project) { artifact.project } let(:project) { artifact.project }
let(:pipeline) { artifact.job.pipeline } let(:pipeline) { artifact.job.pipeline }
let(:report) { Gitlab::Ci::Reports::Security::Report.new(artifact.file_type, pipeline, 2.weeks.ago) } let(:report) { Gitlab::Ci::Reports::Security::Report.new(artifact.file_type, pipeline, 2.weeks.ago) }
before do before do
artifact.each_blob do |blob| artifact.each_blob { |blob| described_class.parse!(blob, report) }
parser.parse!(blob, report)
end
end end
describe '#parse!' do describe '#parse!' do
......
...@@ -6,14 +6,11 @@ RSpec.describe Gitlab::Ci::Parsers::Security::CoverageFuzzing do ...@@ -6,14 +6,11 @@ RSpec.describe Gitlab::Ci::Parsers::Security::CoverageFuzzing do
let(:project) { artifact.project } let(:project) { artifact.project }
let(:pipeline) { artifact.job.pipeline } let(:pipeline) { artifact.job.pipeline }
let(:report) { Gitlab::Ci::Reports::Security::Report.new(artifact.file_type, pipeline, 2.weeks.ago) } let(:report) { Gitlab::Ci::Reports::Security::Report.new(artifact.file_type, pipeline, 2.weeks.ago) }
let(:parser) { described_class.new }
let(:artifact) { create(:ee_ci_job_artifact, :coverage_fuzzing) } let(:artifact) { create(:ee_ci_job_artifact, :coverage_fuzzing) }
describe '#parse!' do describe '#parse!' do
before do before do
artifact.each_blob do |blob| artifact.each_blob { |blob| described_class.parse!(blob, report) }
parser.parse!(blob, report)
end
end end
it 'parses all identifiers and findings' do it 'parses all identifiers and findings' do
......
...@@ -10,7 +10,6 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Dast do ...@@ -10,7 +10,6 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Dast do
let(:pipeline) { artifact.job.pipeline } let(:pipeline) { artifact.job.pipeline }
let(:artifact) { create(:ee_ci_job_artifact, :dast) } let(:artifact) { create(:ee_ci_job_artifact, :dast) }
let(:report) { Gitlab::Ci::Reports::Security::Report.new(artifact.file_type, pipeline, 2.weeks.ago) } let(:report) { Gitlab::Ci::Reports::Security::Report.new(artifact.file_type, pipeline, 2.weeks.ago) }
let(:parser) { described_class.new }
where(:report_format, where(:report_format,
:occurrence_count, :occurrence_count,
...@@ -32,9 +31,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Dast do ...@@ -32,9 +31,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Dast do
let(:artifact) { create(:ee_ci_job_artifact, report_format) } let(:artifact) { create(:ee_ci_job_artifact, report_format) }
before do before do
artifact.each_blob do |blob| artifact.each_blob { |blob| described_class.parse!(blob, report) }
parser.parse!(blob, report)
end
end end
it 'parses all identifiers, findings and scanned resources' do it 'parses all identifiers, findings and scanned resources' do
...@@ -75,9 +72,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Dast do ...@@ -75,9 +72,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Dast do
let(:artifact) { create(:ee_ci_job_artifact, 'dast') } let(:artifact) { create(:ee_ci_job_artifact, 'dast') }
before do before do
artifact.each_blob do |blob| artifact.each_blob { |blob| described_class.parse!(blob, report) }
parser.parse!(blob, report)
end
end end
let(:raw_json) do let(:raw_json) do
...@@ -98,7 +93,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Dast do ...@@ -98,7 +93,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Dast do
end end
it 'skips invalid URLs' do it 'skips invalid URLs' do
parser.parse!(raw_json.to_json, report) described_class.parse!(raw_json.to_json, report)
expect(report.scanned_resources).to be_empty expect(report.scanned_resources).to be_empty
end end
......
...@@ -10,7 +10,6 @@ RSpec.describe Gitlab::Ci::Parsers::Security::DependencyScanning do ...@@ -10,7 +10,6 @@ RSpec.describe Gitlab::Ci::Parsers::Security::DependencyScanning do
let(:pipeline) { artifact.job.pipeline } let(:pipeline) { artifact.job.pipeline }
let(:artifact) { create(:ee_ci_job_artifact, :dependency_scanning) } let(:artifact) { create(:ee_ci_job_artifact, :dependency_scanning) }
let(:report) { Gitlab::Ci::Reports::Security::Report.new(artifact.file_type, pipeline, 2.weeks.ago) } let(:report) { Gitlab::Ci::Reports::Security::Report.new(artifact.file_type, pipeline, 2.weeks.ago) }
let(:parser) { described_class.new }
where(:report_format, :occurrence_count, :identifier_count, :scanner_count, :file_path, :package_name, :package_version, :version) do where(:report_format, :occurrence_count, :identifier_count, :scanner_count, :file_path, :package_name, :package_version, :version) do
:dependency_scanning | 4 | 7 | 3 | 'app/pom.xml' | 'io.netty/netty' | '3.9.1.Final' | '1.3' :dependency_scanning | 4 | 7 | 3 | 'app/pom.xml' | 'io.netty/netty' | '3.9.1.Final' | '1.3'
...@@ -22,9 +21,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::DependencyScanning do ...@@ -22,9 +21,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::DependencyScanning do
let(:artifact) { create(:ee_ci_job_artifact, report_format) } let(:artifact) { create(:ee_ci_job_artifact, report_format) }
before do before do
artifact.each_blob do |blob| artifact.each_blob { |blob| described_class.parse!(blob, report) }
parser.parse!(blob, report)
end
end end
it "parses all identifiers and findings" do it "parses all identifiers and findings" do
...@@ -56,7 +53,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::DependencyScanning do ...@@ -56,7 +53,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::DependencyScanning do
report_hash[:vulnerabilities][0][:location] = nil report_hash[:vulnerabilities][0][:location] = nil
end end
it { expect { parser.parse!(report_hash.to_json, report) }.not_to raise_error } it { expect { described_class.parse!(report_hash.to_json, report) }.not_to raise_error }
end end
context "when parsing a vulnerability with a missing cve" do context "when parsing a vulnerability with a missing cve" do
...@@ -66,16 +63,14 @@ RSpec.describe Gitlab::Ci::Parsers::Security::DependencyScanning do ...@@ -66,16 +63,14 @@ RSpec.describe Gitlab::Ci::Parsers::Security::DependencyScanning do
report_hash[:vulnerabilities][0][:cve] = nil report_hash[:vulnerabilities][0][:cve] = nil
end end
it { expect { parser.parse!(report_hash.to_json, report) }.not_to raise_error } it { expect { described_class.parse!(report_hash.to_json, report) }.not_to raise_error }
end end
context "when vulnerabilities have remediations" do context "when vulnerabilities have remediations" do
let(:artifact) { create(:ee_ci_job_artifact, :dependency_scanning_remediation) } let(:artifact) { create(:ee_ci_job_artifact, :dependency_scanning_remediation) }
before do before do
artifact.each_blob do |blob| artifact.each_blob { |blob| described_class.parse!(blob, report) }
parser.parse!(blob, report)
end
end end
it "generates occurrence with expected remediation" do it "generates occurrence with expected remediation" do
......
...@@ -10,8 +10,6 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Sast do ...@@ -10,8 +10,6 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Sast do
let(:created_at) { 2.weeks.ago } let(:created_at) { 2.weeks.ago }
subject(:parser) { described_class.new }
context "when parsing valid reports" do context "when parsing valid reports" do
where(:report_format, :scanner_length) do where(:report_format, :scanner_length) do
:sast | 4 :sast | 4
...@@ -23,9 +21,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Sast do ...@@ -23,9 +21,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Sast do
let(:artifact) { create(:ee_ci_job_artifact, report_format) } let(:artifact) { create(:ee_ci_job_artifact, report_format) }
before do before do
artifact.each_blob do |blob| artifact.each_blob { |blob| described_class.parse!(blob, report) }
parser.parse!(blob, report)
end
end end
it "parses all identifiers and findings" do it "parses all identifiers and findings" do
...@@ -57,7 +53,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Sast do ...@@ -57,7 +53,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Sast do
let(:report) { Gitlab::Ci::Reports::Security::Report.new('sast', pipeline, created_at) } let(:report) { Gitlab::Ci::Reports::Security::Report.new('sast', pipeline, created_at) }
let(:blob) { Gitlab::Json.generate({}) } let(:blob) { Gitlab::Json.generate({}) }
it { expect(parser.parse!(blob, report)).to be_empty } it { expect(described_class.parse!(blob, report)).to be_empty }
end end
end end
end end
...@@ -8,8 +8,6 @@ RSpec.describe Gitlab::Ci::Parsers::Security::SecretDetection do ...@@ -8,8 +8,6 @@ RSpec.describe Gitlab::Ci::Parsers::Security::SecretDetection do
let(:created_at) { 2.weeks.ago } let(:created_at) { 2.weeks.ago }
subject(:parser) { described_class.new }
context "when parsing valid reports" do context "when parsing valid reports" do
where(report_format: %i(secret_detection)) where(report_format: %i(secret_detection))
...@@ -18,9 +16,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::SecretDetection do ...@@ -18,9 +16,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::SecretDetection do
let(:artifact) { create(:ee_ci_job_artifact, report_format) } let(:artifact) { create(:ee_ci_job_artifact, report_format) }
before do before do
artifact.each_blob do |blob| artifact.each_blob { |blob| described_class.parse!(blob, report) }
parser.parse!(blob, report)
end
end end
it "parses all identifiers and findings" do it "parses all identifiers and findings" do
...@@ -52,7 +48,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::SecretDetection do ...@@ -52,7 +48,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::SecretDetection do
let(:report) { Gitlab::Ci::Reports::Security::Report.new('secret_detection', pipeline, created_at) } let(:report) { Gitlab::Ci::Reports::Security::Report.new('secret_detection', pipeline, created_at) }
let(:blob) { Gitlab::Json.generate({}) } let(:blob) { Gitlab::Json.generate({}) }
it { expect(parser.parse!(blob, report)).to be_empty } it { expect(described_class.parse!(blob, report)).to be_empty }
end end
end end
end end
...@@ -15,8 +15,8 @@ module Gitlab ...@@ -15,8 +15,8 @@ module Gitlab
} }
end end
def self.fabricate!(file_type) def self.fabricate!(file_type, *args)
parsers.fetch(file_type.to_sym).new parsers.fetch(file_type.to_sym).new(*args)
rescue KeyError rescue KeyError
raise ParserNotFoundError, "Cannot find any parser matching file type '#{file_type}'" raise ParserNotFoundError, "Cannot find any parser matching file type '#{file_type}'"
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