Commit 15d4b975 authored by Nikola Milojevic's avatar Nikola Milojevic

Merge branch '276498_introduce_vulnerability_flags_ingestion' into 'master'

Ingest vulnerability flags with the new ingestion flow

See merge request gitlab-org/gitlab!71495
parents 1a8c4d75 57484801
...@@ -4,6 +4,10 @@ module Vulnerabilities ...@@ -4,6 +4,10 @@ module Vulnerabilities
class Flag < ApplicationRecord class Flag < ApplicationRecord
self.table_name = 'vulnerability_flags' self.table_name = 'vulnerability_flags'
# This is necessary to prevent updating the
# created_at attribute with upsert queries.
attr_readonly(:created_at)
belongs_to :finding, class_name: 'Vulnerabilities::Finding', foreign_key: 'vulnerability_occurrence_id', inverse_of: :vulnerability_flags, optional: false belongs_to :finding, class_name: 'Vulnerabilities::Finding', foreign_key: 'vulnerability_occurrence_id', inverse_of: :vulnerability_flags, optional: false
validates :origin, length: { maximum: 255 } validates :origin, length: { maximum: 255 }
......
...@@ -16,6 +16,7 @@ module Security ...@@ -16,6 +16,7 @@ module Security
IngestFindingIdentifiers IngestFindingIdentifiers
IngestFindingLinks IngestFindingLinks
IngestFindingSignatures IngestFindingSignatures
IngestVulnerabilityFlags
IngestRemediations IngestRemediations
].freeze ].freeze
......
# frozen_string_literal: true
module Security
module Ingestion
module Tasks
# Ingests the data for the `Vulnerabilities`::Flag` model.
class IngestVulnerabilityFlags < AbstractTask
include BulkInsertableTask
self.model = Vulnerabilities::Flag
self.unique_by = :index_vulnerability_flags_on_unique_columns
self.uses = :id
private
def attributes
finding_maps.flat_map { |finding_map| flag_attributes_for(finding_map) }
end
def after_ingest
model.where(finding: finding_ids).where.not(id: return_data).delete_all # rubocop:disable CodeReuse/ActiveRecord
end
def finding_ids
finding_maps.map(&:finding_id)
end
def flag_attributes_for(finding_map)
finding_map.report_finding.flags.map do |vulnerability_flag|
vulnerability_flag.to_h.merge!(vulnerability_occurrence_id: finding_map.finding_id)
end
end
end
end
end
end
...@@ -29,6 +29,7 @@ RSpec.describe Security::Ingestion::IngestReportSliceService do ...@@ -29,6 +29,7 @@ RSpec.describe Security::Ingestion::IngestReportSliceService do
expect(Security::Ingestion::Tasks::IngestFindingIdentifiers).to have_received(:execute).ordered.with(pipeline, finding_maps) expect(Security::Ingestion::Tasks::IngestFindingIdentifiers).to have_received(:execute).ordered.with(pipeline, finding_maps)
expect(Security::Ingestion::Tasks::IngestFindingLinks).to have_received(:execute).ordered.with(pipeline, finding_maps) expect(Security::Ingestion::Tasks::IngestFindingLinks).to have_received(:execute).ordered.with(pipeline, finding_maps)
expect(Security::Ingestion::Tasks::IngestFindingSignatures).to have_received(:execute).ordered.with(pipeline, finding_maps) expect(Security::Ingestion::Tasks::IngestFindingSignatures).to have_received(:execute).ordered.with(pipeline, finding_maps)
expect(Security::Ingestion::Tasks::IngestVulnerabilityFlags).to have_received(:execute).ordered.with(pipeline, finding_maps)
expect(Security::Ingestion::Tasks::IngestRemediations).to have_received(:execute).ordered.with(pipeline, finding_maps) expect(Security::Ingestion::Tasks::IngestRemediations).to have_received(:execute).ordered.with(pipeline, finding_maps)
end end
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Security::Ingestion::Tasks::IngestVulnerabilityFlags do
describe '#execute' do
let_it_be(:pipeline) { create(:ci_pipeline) }
let(:vulnerability_finding) { create(:vulnerabilities_finding) }
let!(:existing_vulnerability_flag_1) { create(:vulnerabilities_flag, origin: 'post analyzer 1', finding: vulnerability_finding) }
let!(:existing_vulnerability_flag_2) { create(:vulnerabilities_flag, origin: 'post analyzer 2', finding: vulnerability_finding, description: 'foo') }
let(:report_finding_flag_2) { create(:ci_reports_security_flag, origin: 'post analyzer 2', description: 'bar') }
let(:report_finding_flag_3) { create(:ci_reports_security_flag, origin: 'post analyzer 3') }
let(:report_finding_flag_4) { create(:ci_reports_security_flag, origin: 'post analyzer 4') }
let(:report_finding) { create(:ci_reports_security_finding, flags: [report_finding_flag_2, report_finding_flag_3, report_finding_flag_4]) }
let(:finding_map) { create(:finding_map, finding: vulnerability_finding, report_finding: report_finding) }
let(:service_object) { described_class.new(pipeline, [finding_map]) }
subject(:ingest_vulnerability_flags) { service_object.execute }
it 'creates new records and updates the existing ones' do
expect { ingest_vulnerability_flags }.to change { vulnerability_finding.vulnerability_flags.count }.from(2).to(3)
.and change { existing_vulnerability_flag_2.reload.description }.from('foo').to('bar')
end
it 'deletes the old records' do
expect { ingest_vulnerability_flags }.to change { Vulnerabilities::Flag.find_by_id(existing_vulnerability_flag_1.id) }.to(nil)
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