Commit 97257671 authored by Mehmet Emin INAC's avatar Mehmet Emin INAC

Do not parse Finding#raw_metadata to collect attributes

We can collect the attributes directly from the finding data instead of
serializing the data as string and then parsing the json string.
parent 7020dc6c
...@@ -8,9 +8,7 @@ module Security ...@@ -8,9 +8,7 @@ module Security
# You can think this as the Message object in the pipeline design pattern # You can think this as the Message object in the pipeline design pattern
# which is passed between tasks. # which is passed between tasks.
class FindingMap class FindingMap
FINDING_ATTRIBUTES = %i[confidence metadata_version name raw_metadata report_type severity details].freeze FINDING_ATTRIBUTES = %i[confidence metadata_version name raw_metadata report_type severity details description message cve solution].freeze
RAW_METADATA_ATTRIBUTES = %w[description message solution cve location].freeze
RAW_METADATA_PLACEHOLDER = { description: nil, message: nil, solution: nil, cve: nil, location: nil }.freeze
attr_reader :security_finding, :report_finding attr_reader :security_finding, :report_finding
attr_accessor :finding_id, :vulnerability_id, :new_record, :identifier_ids attr_accessor :finding_id, :vulnerability_id, :new_record, :identifier_ids
...@@ -44,16 +42,16 @@ module Security ...@@ -44,16 +42,16 @@ module Security
end end
def to_hash def to_hash
# This was already an existing problem so we've used it here as well.
# TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/342043
parsed_from_raw_metadata = Gitlab::Json.parse(report_finding.raw_metadata).slice(*RAW_METADATA_ATTRIBUTES).symbolize_keys
report_finding.to_hash report_finding.to_hash
.slice(*FINDING_ATTRIBUTES) .slice(*FINDING_ATTRIBUTES)
.merge(RAW_METADATA_PLACEHOLDER) .merge!(
.merge(parsed_from_raw_metadata) uuid: uuid,
.merge(primary_identifier_id: identifier_ids.first, location_fingerprint: report_finding.location.fingerprint, project_fingerprint: project_fingerprint) scanner_id: scanner_id,
.merge(uuid: uuid, scanner_id: scanner_id) project_fingerprint: project_fingerprint,
primary_identifier_id: identifier_ids.first,
location: report_finding.location_data,
location_fingerprint: report_finding.location.fingerprint
)
end end
end end
end end
......
...@@ -29,7 +29,7 @@ RSpec.describe Gitlab::Ci::Reports::Security::Finding do ...@@ -29,7 +29,7 @@ RSpec.describe Gitlab::Ci::Reports::Security::Finding do
location: location, location: location,
metadata_version: 'sast:1.0', metadata_version: 'sast:1.0',
name: 'Cipher with no integrity', name: 'Cipher with no integrity',
raw_metadata: 'I am a stringified json object', original_data: {},
report_type: :sast, report_type: :sast,
scanner: scanner, scanner: scanner,
scan: nil, scan: nil,
...@@ -71,7 +71,8 @@ RSpec.describe Gitlab::Ci::Reports::Security::Finding do ...@@ -71,7 +71,8 @@ RSpec.describe Gitlab::Ci::Reports::Security::Finding do
location: location, location: location,
metadata_version: 'sast:1.0', metadata_version: 'sast:1.0',
name: 'Cipher with no integrity', name: 'Cipher with no integrity',
raw_metadata: 'I am a stringified json object', raw_metadata: '{}',
original_data: {},
report_type: :sast, report_type: :sast,
scanner: scanner, scanner: scanner,
severity: :high, severity: :high,
...@@ -98,7 +99,7 @@ RSpec.describe Gitlab::Ci::Reports::Security::Finding do ...@@ -98,7 +99,7 @@ RSpec.describe Gitlab::Ci::Reports::Security::Finding do
end end
end end
%i[compare_key identifiers location metadata_version name raw_metadata report_type scanner uuid].each do |attribute| %i[compare_key identifiers location metadata_version name original_data report_type scanner uuid].each do |attribute|
context "when attribute #{attribute} is missing" do context "when attribute #{attribute} is missing" do
before do before do
params.delete(attribute) params.delete(attribute)
...@@ -144,6 +145,10 @@ RSpec.describe Gitlab::Ci::Reports::Security::Finding do ...@@ -144,6 +145,10 @@ RSpec.describe Gitlab::Ci::Reports::Security::Finding do
severity: occurrence.severity, severity: occurrence.severity,
uuid: occurrence.uuid, uuid: occurrence.uuid,
details: occurrence.details, details: occurrence.details,
cve: occurrence.compare_key,
description: occurrence.description,
message: occurrence.message,
solution: occurrence.solution,
signatures: [] signatures: []
}) })
end end
......
...@@ -61,7 +61,7 @@ RSpec.describe Security::Ingestion::FindingMap do ...@@ -61,7 +61,7 @@ RSpec.describe Security::Ingestion::FindingMap do
description: 'The cipher does not provide data integrity update 1', description: 'The cipher does not provide data integrity update 1',
solution: 'GCM mode introduces an HMAC into the resulting encrypted data, providing integrity of the result.', solution: 'GCM mode introduces an HMAC into the resulting encrypted data, providing integrity of the result.',
message: nil, message: nil,
cve: nil, cve: report_finding.cve,
location: { location: {
"class" => "com.gitlab.security_products.tests.App", "class" => "com.gitlab.security_products.tests.App",
"end_line" => 29, "end_line" => 29,
......
...@@ -114,7 +114,7 @@ module Gitlab ...@@ -114,7 +114,7 @@ module Gitlab
flags: flags, flags: flags,
links: links, links: links,
remediations: remediations, remediations: remediations,
raw_metadata: data.to_json, original_data: data,
metadata_version: report_version, metadata_version: report_version,
details: data['details'] || {}, details: data['details'] || {},
signatures: signatures, signatures: signatures,
......
...@@ -17,7 +17,6 @@ module Gitlab ...@@ -17,7 +17,6 @@ module Gitlab
attr_reader :name attr_reader :name
attr_reader :old_location attr_reader :old_location
attr_reader :project_fingerprint attr_reader :project_fingerprint
attr_reader :raw_metadata
attr_reader :report_type attr_reader :report_type
attr_reader :scanner attr_reader :scanner
attr_reader :scan attr_reader :scan
...@@ -28,10 +27,13 @@ module Gitlab ...@@ -28,10 +27,13 @@ module Gitlab
attr_reader :details attr_reader :details
attr_reader :signatures attr_reader :signatures
attr_reader :project_id attr_reader :project_id
attr_reader :original_data
delegate :file_path, :start_line, :end_line, to: :location delegate :file_path, :start_line, :end_line, to: :location
def initialize(compare_key:, identifiers:, flags: [], links: [], remediations: [], location:, metadata_version:, name:, raw_metadata:, report_type:, scanner:, scan:, uuid:, confidence: nil, severity: nil, details: {}, signatures: [], project_id: nil, vulnerability_finding_signatures_enabled: false) # rubocop:disable Metrics/ParameterLists alias_method :cve, :compare_key
def initialize(compare_key:, identifiers:, flags: [], links: [], remediations: [], location:, metadata_version:, name:, original_data:, report_type:, scanner:, scan:, uuid:, confidence: nil, severity: nil, details: {}, signatures: [], project_id: nil, vulnerability_finding_signatures_enabled: false) # rubocop:disable Metrics/ParameterLists
@compare_key = compare_key @compare_key = compare_key
@confidence = confidence @confidence = confidence
@identifiers = identifiers @identifiers = identifiers
...@@ -40,7 +42,7 @@ module Gitlab ...@@ -40,7 +42,7 @@ module Gitlab
@location = location @location = location
@metadata_version = metadata_version @metadata_version = metadata_version
@name = name @name = name
@raw_metadata = raw_metadata @original_data = original_data
@report_type = report_type @report_type = report_type
@scanner = scanner @scanner = scanner
@scan = scan @scan = scan
...@@ -74,6 +76,10 @@ module Gitlab ...@@ -74,6 +76,10 @@ module Gitlab
uuid uuid
details details
signatures signatures
description
message
cve
solution
].each_with_object({}) do |key, hash| ].each_with_object({}) do |key, hash|
hash[key] = public_send(key) # rubocop:disable GitlabSecurity/PublicSend hash[key] = public_send(key) # rubocop:disable GitlabSecurity/PublicSend
end end
...@@ -145,6 +151,26 @@ module Gitlab ...@@ -145,6 +151,26 @@ module Gitlab
signatures.present? signatures.present?
end end
def raw_metadata
@raw_metadata ||= original_data.to_json
end
def description
original_data['description']
end
def message
original_data['message']
end
def solution
original_data['solution']
end
def location_data
original_data['location']
end
private private
def generate_project_fingerprint def generate_project_fingerprint
......
...@@ -9,7 +9,7 @@ FactoryBot.define do ...@@ -9,7 +9,7 @@ FactoryBot.define do
metadata_version { 'sast:1.0' } metadata_version { 'sast:1.0' }
name { 'Cipher with no integrity' } name { 'Cipher with no integrity' }
report_type { :sast } report_type { :sast }
raw_metadata do original_data do
{ {
description: "The cipher does not provide data integrity update 1", description: "The cipher does not provide data integrity update 1",
solution: "GCM mode introduces an HMAC into the resulting encrypted data, providing integrity of the result.", solution: "GCM mode introduces an HMAC into the resulting encrypted data, providing integrity of the result.",
...@@ -26,7 +26,7 @@ FactoryBot.define do ...@@ -26,7 +26,7 @@ FactoryBot.define do
url: "https://crypto.stackexchange.com/questions/31428/pbewithmd5anddes-cipher-does-not-check-for-integrity-first" url: "https://crypto.stackexchange.com/questions/31428/pbewithmd5anddes-cipher-does-not-check-for-integrity-first"
} }
] ]
}.to_json }.deep_stringify_keys
end end
scanner factory: :ci_reports_security_scanner scanner factory: :ci_reports_security_scanner
severity { :high } severity { :high }
......
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