From 14053e9f8fcaf4670b441b81ce6765d20cd1ac1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zaj=C4=85c?= Date: Wed, 30 Sep 2020 17:30:33 +0200 Subject: [PATCH 1/2] Create CalculateFindingUUID service object --- .../vulnerabilities/calculate_finding_uuid.rb | 28 ++++++++++++ .../calculate_finding_uuid_spec.rb | 45 +++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 ee/lib/gitlab/vulnerabilities/calculate_finding_uuid.rb create mode 100644 ee/spec/lib/gitlab/vulnerabilities/calculate_finding_uuid_spec.rb diff --git a/ee/lib/gitlab/vulnerabilities/calculate_finding_uuid.rb b/ee/lib/gitlab/vulnerabilities/calculate_finding_uuid.rb new file mode 100644 index 00000000000000..a7a9fd8c40a77b --- /dev/null +++ b/ee/lib/gitlab/vulnerabilities/calculate_finding_uuid.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +module Gitlab + module Vulnerabilities + class CalculateFindingUUID + FINDING_NAMESPACES_IDS = { + development: "a143e9e2-41b3-47bc-9a19-081d089229f4", + test: "a143e9e2-41b3-47bc-9a19-081d089229f4", + staging: "a6930898-a1b2-4365-ab18-12aa474d9b26", + production: "58dc0f06-936c-43b3-93bb-71693f1b6570" + }.freeze + + NAMESPACE_REGEX = /(\h{8})-(\h{4})-(\h{4})-(\h{4})-(\h{4})(\h{8})/.freeze + PACK_PATTERN = "NnnnnN".freeze + + def self.call(value) + Digest::UUID.uuid_v5(namespace_id, value) + end + + def self.namespace_id + namespace_uuid = FINDING_NAMESPACES_IDS.fetch(Rails.env.to_sym) + # Digest::UUID is broken when using an UUID in namespace_id + # https://github.com/rails/rails/issues/37681#issue-520718028 + namespace_uuid.scan(NAMESPACE_REGEX).flatten.map { |s| s.to_i(16) }.pack(PACK_PATTERN) + end + end + end +end diff --git a/ee/spec/lib/gitlab/vulnerabilities/calculate_finding_uuid_spec.rb b/ee/spec/lib/gitlab/vulnerabilities/calculate_finding_uuid_spec.rb new file mode 100644 index 00000000000000..74894ba5ef383b --- /dev/null +++ b/ee/spec/lib/gitlab/vulnerabilities/calculate_finding_uuid_spec.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Vulnerabilities::CalculateFindingUUID do + let_it_be(:value) { "GitLab" } + + subject { described_class.call(value) } + + context 'in development' do + let_it_be(:development_proper_uuid) { "5b593e54-90f5-504b-8805-5394a4d14b94" } + + before do + allow(Rails).to receive(:env).and_return(:development) + end + + it { is_expected.to eq(development_proper_uuid) } + end + + context 'in test' do + let_it_be(:test_proper_uuid) { "5b593e54-90f5-504b-8805-5394a4d14b94" } + + it { is_expected.to eq(test_proper_uuid) } + end + + context 'in staging' do + let_it_be(:staging_proper_uuid) { "dd190b37-7754-5c7c-80a0-85621a5823ad" } + + before do + allow(Rails).to receive(:env).and_return(:staging) + end + + it { is_expected.to eq(staging_proper_uuid) } + end + + context 'in production' do + let_it_be(:production_proper_uuid) { "4961388b-9d8e-5da0-a499-3ef5da58daf0" } + + before do + allow(Rails).to receive(:env).and_return(:production) + end + + it { is_expected.to eq(production_proper_uuid) } + end +end -- GitLab From 839a34f329d26cf58c6b6dc3c6d7a0c8cce390bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zaj=C4=85c?= Date: Wed, 30 Sep 2020 17:31:42 +0200 Subject: [PATCH 2/2] Calculate UUIDv5 for Finding before saving --- .../services/security/store_report_service.rb | 26 +++++++++++++++++-- .../security/store_report_service_spec.rb | 8 ++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/ee/app/services/security/store_report_service.rb b/ee/app/services/security/store_report_service.rb index 2dc637cf086bf6..80f09abd88bc44 100644 --- a/ee/app/services/security/store_report_service.rb +++ b/ee/app/services/security/store_report_service.rb @@ -72,10 +72,15 @@ def create_or_find_vulnerability_finding(finding, create_params) } begin - project + vulnerability_finding = project .vulnerability_findings .create_with(create_params) - .find_or_create_by!(find_params) + .find_or_initialize_by(find_params) + + vulnerability_finding.uuid = calculcate_uuid_v5(vulnerability_finding, find_params) + + vulnerability_finding.save! + vulnerability_finding rescue ActiveRecord::RecordNotUnique project.vulnerability_findings.find_by!(find_params) rescue ActiveRecord::RecordInvalid => e @@ -83,6 +88,23 @@ def create_or_find_vulnerability_finding(finding, create_params) end end + def calculcate_uuid_v5(vulnerability_finding, finding_params) + uuid_v5_name_components = { + report_type: vulnerability_finding.report_type, + primary_identifier_fingerprint: vulnerability_finding.primary_identifier&.fingerprint || finding_params.dig(:primary_identifier, :fingerprint), + location_fingerprint: vulnerability_finding.location_fingerprint, + project_id: project.id + } + + if uuid_v5_name_components.values.any?(&:nil?) + Gitlab::AppLogger.warn(message: "One or more UUID name components are nil", components: uuid_v5_name_components) + end + + name = uuid_v5_name_components.values.join('-') + + Gitlab::Vulnerabilities::CalculateFindingUUID.call(name) + end + def update_vulnerability_scanner(finding) scanner = scanners_objects[finding.scanner.key] scanner.update!(finding.scanner.to_hash) diff --git a/ee/spec/services/security/store_report_service_spec.rb b/ee/spec/services/security/store_report_service_spec.rb index 0dd1a51fd43487..d31bce178515ae 100644 --- a/ee/spec/services/security/store_report_service_spec.rb +++ b/ee/spec/services/security/store_report_service_spec.rb @@ -53,6 +53,10 @@ it 'inserts all vulnerabilties' do expect { subject }.to change { Vulnerability.count }.by(findings) end + + it 'calculates UUIDv5 for all findings' do + expect(Vulnerabilities::Finding.pluck(:uuid)).to all(be_a(String)) + end end context 'invalid data' do @@ -118,6 +122,10 @@ expect { subject }.to change { Vulnerabilities::Finding.count }.by(32) end + it 'calculates UUIDv5 for all findings' do + expect(Vulnerabilities::Finding.pluck(:uuid)).to all(be_a(String)) + end + it 'inserts all finding pipelines (join model) for this new pipeline' do expect { subject }.to change { Vulnerabilities::FindingPipeline.where(pipeline: new_pipeline).count }.by(33) end -- GitLab