Commit b11ed0e3 authored by Mehmet Emin INAC's avatar Mehmet Emin INAC Committed by Stan Hu

Fix the private interface of Security parsers

We don't need to pass the `report_data` and `report` objects around the
method as they are now attributes of the parser instance.
parent a0ffffd0
......@@ -19,12 +19,9 @@ module Gitlab
def parse!
raise SecurityReportParserError, "Invalid report format" unless report_data.is_a?(Hash)
create_scanner(report, report_data.dig('scan', 'scanner'))
create_scan(report, report_data.dig('scan'))
collate_remediations(report_data).each do |vulnerability|
create_vulnerability(report, vulnerability, report_data["version"])
end
create_scanner
create_scan
collate_remediations.each { |vulnerability| create_vulnerability(vulnerability) }
report_data
rescue JSON::ParserError
......@@ -42,19 +39,30 @@ module Gitlab
@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 scan_data
@scan_data ||= report_data.dig('scan')
end
# map remediations to relevant vulnerabilities
def collate_remediations(report_data)
def collate_remediations
return report_data["vulnerabilities"] || [] unless report_data["remediations"]
fixes = fixes_from(report_data)
report_data["vulnerabilities"].map do |vulnerability|
remediation = fixes[vulnerability['id']] || fixes[vulnerability['cve']]
vulnerability.merge("remediations" => [remediation])
end
end
def fixes_from(report_data)
report_data['remediations'].each_with_object({}) do |item, memo|
def fixes
@fixes ||= report_data['remediations'].each_with_object({}) do |item, memo|
item['fixes'].each do |fix|
id = fix['id'] || fix['cve']
memo[id] = item if id
......@@ -63,56 +71,54 @@ module Gitlab
end
end
def create_vulnerability(report, data, version)
identifiers = create_identifiers(report, data['identifiers'])
links = create_links(report, data['links'])
def create_vulnerability(data)
identifiers = create_identifiers(data['identifiers'])
links = create_links(data['links'])
location = create_location(data['location'] || {})
remediations = create_remediations(data['remediations'])
report.add_finding(
::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,
name: finding_name(data, identifiers, location),
compare_key: data['cve'] || '',
location: location,
severity: parse_severity_level(data['severity']&.downcase),
confidence: parse_confidence_level(data['confidence']&.downcase),
scanner: create_scanner(report, data['scanner']),
severity: parse_severity_level(data['severity']),
confidence: parse_confidence_level(data['confidence']),
scanner: create_scanner(data['scanner']),
scan: report&.scan,
identifiers: identifiers,
links: links,
remediations: remediations,
raw_metadata: data.to_json,
metadata_version: version,
metadata_version: report_version,
details: data['details'] || {}))
end
def create_scan(report, scan_data)
def create_scan
return unless scan_data.is_a?(Hash)
report.scan = ::Gitlab::Ci::Reports::Security::Scan.new(scan_data)
end
def create_scanner(report, scanner)
return unless scanner.is_a?(Hash)
def create_scanner(scanner_data = top_level_scanner)
return unless scanner_data.is_a?(Hash)
report.add_scanner(
::Gitlab::Ci::Reports::Security::Scanner.new(
external_id: scanner['id'],
name: scanner['name'],
vendor: scanner.dig('vendor', 'name')))
external_id: scanner_data['id'],
name: scanner_data['name'],
vendor: scanner_data.dig('vendor', 'name')))
end
def create_identifiers(report, identifiers)
def create_identifiers(identifiers)
return [] unless identifiers.is_a?(Array)
identifiers.map do |identifier|
create_identifier(report, identifier)
end.compact
identifiers.map { |identifier| create_identifier(identifier) }.compact
end
def create_identifier(report, identifier)
def create_identifier(identifier)
return unless identifier.is_a?(Hash)
report.add_identifier(
......@@ -123,20 +129,16 @@ module Gitlab
url: identifier['url']))
end
def create_links(report, links)
def create_links(links)
return [] unless links.is_a?(Array)
links
.map { |link| create_link(report, link) }
.compact
links.map { |link| create_link(link) }.compact
end
def create_link(report, link)
def create_link(link)
return unless link.is_a?(Hash)
::Gitlab::Ci::Reports::Security::Link.new(
name: link['name'],
url: link['url'])
::Gitlab::Ci::Reports::Security::Link.new(name: link['name'], url: link['url'])
end
def create_remediations(remediations_data)
......@@ -146,15 +148,11 @@ module Gitlab
end
def parse_severity_level(input)
return input if ::Enums::Vulnerability.severity_levels.key?(input)
'unknown'
input&.downcase.then { |value| ::Enums::Vulnerability.severity_levels.key?(value) ? value : 'unknown' }
end
def parse_confidence_level(input)
return input if ::Enums::Vulnerability.confidence_levels.key?(input)
'unknown'
input&.downcase.then { |value| ::Enums::Vulnerability.confidence_levels.key?(value) ? value : 'unknown' }
end
def create_location(location_data)
......@@ -169,7 +167,7 @@ module Gitlab
"#{identifier.name} in #{location&.fingerprint_path}"
end
def calculate_uuid_v5(report, location, primary_identifier)
def calculate_uuid_v5(primary_identifier, location)
uuid_v5_name_components = {
report_type: report.type,
primary_identifier_fingerprint: primary_identifier&.fingerprint,
......
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