Commit 168adf9f authored by Dylan Griffith's avatar Dylan Griffith

Merge branch 'parse-new-scan-object' into 'master'

Parse new scan object

See merge request gitlab-org/gitlab!43736
parents 55084497 417ccb03
...@@ -47,7 +47,7 @@ module Security ...@@ -47,7 +47,7 @@ module Security
return return
end end
vulnerability_params = finding.to_hash.except(:compare_key, :identifiers, :location, :scanner) vulnerability_params = finding.to_hash.except(:compare_key, :identifiers, :location, :scanner, :scan)
vulnerability_finding = create_or_find_vulnerability_finding(finding, vulnerability_params) vulnerability_finding = create_or_find_vulnerability_finding(finding, vulnerability_params)
update_vulnerability_scanner(finding) update_vulnerability_scanner(finding)
......
...@@ -12,6 +12,7 @@ module Gitlab ...@@ -12,6 +12,7 @@ module Gitlab
raise SecurityReportParserError, "Invalid report format" unless report_data.is_a?(Hash) raise SecurityReportParserError, "Invalid report format" unless report_data.is_a?(Hash)
create_scanner(report, report_data.dig('scan', 'scanner')) create_scanner(report, report_data.dig('scan', 'scanner'))
create_scan(report, report_data.dig('scan'))
collate_remediations(report_data).each do |vulnerability| collate_remediations(report_data).each do |vulnerability|
create_vulnerability(report, vulnerability, report_data["version"]) create_vulnerability(report, vulnerability, report_data["version"])
...@@ -53,7 +54,6 @@ module Gitlab ...@@ -53,7 +54,6 @@ module Gitlab
end end
def create_vulnerability(report, data, version) def create_vulnerability(report, data, version)
scanner = create_scanner(report, data['scanner'])
identifiers = create_identifiers(report, data['identifiers']) identifiers = create_identifiers(report, data['identifiers'])
report.add_finding( report.add_finding(
::Gitlab::Ci::Reports::Security::Finding.new( ::Gitlab::Ci::Reports::Security::Finding.new(
...@@ -64,12 +64,19 @@ module Gitlab ...@@ -64,12 +64,19 @@ module Gitlab
location: create_location(data['location'] || {}), location: create_location(data['location'] || {}),
severity: parse_severity_level(data['severity']&.downcase), severity: parse_severity_level(data['severity']&.downcase),
confidence: parse_confidence_level(data['confidence']&.downcase), confidence: parse_confidence_level(data['confidence']&.downcase),
scanner: scanner, scanner: create_scanner(report, data['scanner']),
scan: report&.scan,
identifiers: identifiers, identifiers: identifiers,
raw_metadata: data.to_json, raw_metadata: data.to_json,
metadata_version: version)) metadata_version: version))
end end
def create_scan(report, scan_data)
return unless scan_data.is_a?(Hash)
report.scan = ::Gitlab::Ci::Reports::Security::Scan.new(scan_data)
end
def create_scanner(report, scanner) def create_scanner(report, scanner)
return unless scanner.is_a?(Hash) return unless scanner.is_a?(Hash)
......
...@@ -18,12 +18,13 @@ module Gitlab ...@@ -18,12 +18,13 @@ module Gitlab
attr_reader :raw_metadata attr_reader :raw_metadata
attr_reader :report_type attr_reader :report_type
attr_reader :scanner attr_reader :scanner
attr_reader :scan
attr_reader :severity attr_reader :severity
attr_reader :uuid attr_reader :uuid
delegate :file_path, :start_line, :end_line, to: :location delegate :file_path, :start_line, :end_line, to: :location
def initialize(compare_key:, identifiers:, location:, metadata_version:, name:, raw_metadata:, report_type:, scanner:, uuid:, confidence: nil, severity: nil) # rubocop:disable Metrics/ParameterLists def initialize(compare_key:, identifiers:, location:, metadata_version:, name:, raw_metadata:, report_type:, scanner:, scan:, uuid:, confidence: nil, severity: nil) # rubocop:disable Metrics/ParameterLists
@compare_key = compare_key @compare_key = compare_key
@confidence = confidence @confidence = confidence
@identifiers = identifiers @identifiers = identifiers
...@@ -33,6 +34,7 @@ module Gitlab ...@@ -33,6 +34,7 @@ module Gitlab
@raw_metadata = raw_metadata @raw_metadata = raw_metadata
@report_type = report_type @report_type = report_type
@scanner = scanner @scanner = scanner
@scan = scan
@severity = severity @severity = severity
@uuid = uuid @uuid = uuid
......
...@@ -12,6 +12,7 @@ module Gitlab ...@@ -12,6 +12,7 @@ module Gitlab
attr_reader :scanners attr_reader :scanners
attr_reader :identifiers attr_reader :identifiers
attr_accessor :scan
attr_accessor :scanned_resources attr_accessor :scanned_resources
attr_accessor :error attr_accessor :error
......
# frozen_string_literal: true
module Gitlab
module Ci
module Reports
module Security
class Scan
attr_accessor :type, :status, :start_time, :end_time
def initialize(params = {})
@type = params.dig('type')
@status = params.dig('status')
@start_time = params.dig('start_time')
@end_time = params.dig('end_time')
end
def to_hash
{
type: type,
status: status,
start_time: start_time,
end_time: end_time
}.compact
end
end
end
end
end
end
...@@ -30,6 +30,7 @@ FactoryBot.define do ...@@ -30,6 +30,7 @@ FactoryBot.define do
end end
scanner factory: :ci_reports_security_scanner scanner factory: :ci_reports_security_scanner
severity { :high } severity { :high }
scan factory: :ci_reports_security_scan
sequence(:uuid) { generate(:vulnerability_finding_uuid) } sequence(:uuid) { generate(:vulnerability_finding_uuid) }
skip_create skip_create
......
...@@ -12,4 +12,17 @@ FactoryBot.define do ...@@ -12,4 +12,17 @@ FactoryBot.define do
::Gitlab::Ci::Reports::Security::Scanner.new(**attributes) ::Gitlab::Ci::Reports::Security::Scanner.new(**attributes)
end end
end end
factory :ci_reports_security_scan, class: '::Gitlab::Ci::Reports::Security::Scan' do
status { 'success' }
type { 'sast' }
start_time { 'placeholder' }
end_time { 'placeholder' }
skip_create
initialize_with do
::Gitlab::Ci::Reports::Security::Scan.new(attributes)
end
end
end end
...@@ -57,5 +57,26 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do ...@@ -57,5 +57,26 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
end end
end end
end end
context 'parsing scan' do
it 'returns scan object for each finding' do
scans = report.findings.map(&:scan)
expect(scans.map(&:status).all?('success')).to be(true)
expect(scans.map(&:type).all?('dependency_scanning')).to be(true)
expect(scans.map(&:start_time).all?('placeholder-value')).to be(true)
expect(scans.map(&:end_time).all?('placeholder-value')).to be(true)
expect(scans.size).to eq(3)
expect(scans.first).to be_a(::Gitlab::Ci::Reports::Security::Scan)
end
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)
parser.parse!({}.to_json, empty_report)
expect(empty_report.scan).to be(nil)
end
end
end end
end end
...@@ -24,6 +24,7 @@ RSpec.describe Gitlab::Ci::Reports::Security::Finding do ...@@ -24,6 +24,7 @@ RSpec.describe Gitlab::Ci::Reports::Security::Finding do
raw_metadata: 'I am a stringified json object', raw_metadata: 'I am a stringified json object',
report_type: :sast, report_type: :sast,
scanner: scanner, scanner: scanner,
scan: nil,
severity: :high, severity: :high,
uuid: 'cadf8cf0a8228fa92a0f4897a0314083bb38' uuid: 'cadf8cf0a8228fa92a0f4897a0314083bb38'
} }
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Ci::Reports::Security::Scan do
describe '#initialize' do
subject { described_class.new(params.with_indifferent_access) }
let(:params) do
{
status: 'success',
type: 'dependency-scanning',
start_time: 'placeholer',
end_time: 'placholder'
}
end
context 'when all params are given' do
it 'initializes an instance' do
expect { subject }.not_to raise_error
expect(subject).to have_attributes(
status: 'success',
type: 'dependency-scanning',
start_time: 'placeholer',
end_time: 'placholder'
)
end
end
describe '#to_hash' do
subject { described_class.new(params.with_indifferent_access).to_hash }
it 'returns expected hash' do
is_expected.to eq(
{
status: 'success',
type: 'dependency-scanning',
start_time: 'placeholer',
end_time: 'placholder'
}
)
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