1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::MigrateEvidencesForVulnerabilityFindings,
feature_category: :vulnerability_management do
let(:vulnerability_occurrences) { table(:vulnerability_occurrences) }
let(:vulnerability_finding_evidences) { table(:vulnerability_finding_evidences) }
let(:evidence_hash) { { url: 'http://test.com' } }
let(:namespace1) { table(:namespaces).create!(name: 'namespace 1', path: 'namespace1') }
let(:project1) { table(:projects).create!(namespace_id: namespace1.id, project_namespace_id: namespace1.id) }
let(:user) { table(:users).create!(email: 'test1@example.com', projects_limit: 5) }
let(:scanner1) do
table(:vulnerability_scanners).create!(project_id: project1.id, external_id: 'test 1', name: 'test scanner 1')
end
let(:stating_id) { vulnerability_occurrences.pluck(:id).min }
let(:end_id) { vulnerability_occurrences.pluck(:id).max }
let(:migration) do
described_class.new(
start_id: stating_id,
end_id: end_id,
batch_table: :vulnerability_occurrences,
batch_column: :id,
sub_batch_size: 2,
pause_ms: 2,
connection: ApplicationRecord.connection
)
end
subject(:perform_migration) { migration.perform }
context 'without the presence of evidence key' do
before do
create_finding!(project1.id, scanner1.id, { other_keys: 'test' })
end
it 'does not create any evidence' do
expect { perform_migration }.not_to change { vulnerability_finding_evidences.count }
end
end
context 'with evidence equals to nil' do
before do
create_finding!(project1.id, scanner1.id, { evidence: nil })
end
it 'does not create any evidence' do
expect { perform_migration }.not_to change { vulnerability_finding_evidences.count }
end
end
context 'with existing evidence within raw_metadata' do
let!(:finding1) { create_finding!(project1.id, scanner1.id, { evidence: evidence_hash }) }
let!(:finding2) { create_finding!(project1.id, scanner1.id, { evidence: evidence_hash }) }
it 'creates new evidence for each finding' do
expect { perform_migration }.to change { vulnerability_finding_evidences.count }.by(2)
end
context 'when parse throws exception JSON::ParserError' do
before do
allow(Gitlab::Json).to receive(:parse).and_raise(JSON::ParserError)
end
it 'does not create new records' do
expect { perform_migration }.not_to change { vulnerability_finding_evidences.count }
end
end
end
context 'with existing evidence records' do
let!(:finding) { create_finding!(project1.id, scanner1.id, { evidence: evidence_hash }) }
before do
vulnerability_finding_evidences.create!(vulnerability_occurrence_id: finding.id, data: evidence_hash)
end
it 'does not create new evidence' do
expect { perform_migration }.not_to change { vulnerability_finding_evidences.count }
end
context 'with non-existing evidence' do
let!(:finding3) { create_finding!(project1.id, scanner1.id, { evidence: { url: 'http://secondary.com' } }) }
it 'creates a new evidence only to the non-existing evidence' do
expect { perform_migration }.to change { vulnerability_finding_evidences.count }.by(1)
end
end
end
private
def create_finding!(project_id, scanner_id, raw_metadata)
vulnerability = table(:vulnerabilities).create!(project_id: project_id, author_id: user.id, title: 'test',
severity: 4, confidence: 4, report_type: 0)
identifier = table(:vulnerability_identifiers).create!(project_id: project_id, external_type: 'uuid-v5',
external_id: 'uuid-v5', fingerprint: OpenSSL::Digest::SHA256.hexdigest(vulnerability.id.to_s),
name: 'Identifier for UUIDv5 2 2')
table(:vulnerability_occurrences).create!(
vulnerability_id: vulnerability.id, project_id: project_id, scanner_id: scanner_id,
primary_identifier_id: identifier.id, name: 'test', severity: 4, confidence: 4, report_type: 0,
uuid: SecureRandom.uuid, project_fingerprint: '123qweasdzxc', location: { "image" => "alpine:3.4" },
location_fingerprint: 'test', metadata_version: 'test',
raw_metadata: raw_metadata.to_json)
end
end
|