Commit adcf3d51 authored by Tetiana Chupryna's avatar Tetiana Chupryna

Use finding_evidence over raw_metadata

Replace raw_metadata with finding_evidence.data.
We keep current response structure.

Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/343280

Changelog: changed
EE: true
parent c3b4ef1a
...@@ -39,7 +39,7 @@ module Vulnerabilities ...@@ -39,7 +39,7 @@ module Vulnerabilities
has_many :vulnerability_flags, class_name: 'Vulnerabilities::Flag', inverse_of: :finding, foreign_key: 'vulnerability_occurrence_id' has_many :vulnerability_flags, class_name: 'Vulnerabilities::Flag', inverse_of: :finding, foreign_key: 'vulnerability_occurrence_id'
has_one :evidence, class_name: 'Vulnerabilities::Finding::Evidence', inverse_of: :finding, foreign_key: 'vulnerability_occurrence_id' has_one :finding_evidence, class_name: 'Vulnerabilities::Finding::Evidence', inverse_of: :finding, foreign_key: 'vulnerability_occurrence_id'
serialize :config_options, Serializers::Json # rubocop:disable Cop/ActiveRecordSerialize serialize :config_options, Serializers::Json # rubocop:disable Cop/ActiveRecordSerialize
...@@ -281,12 +281,14 @@ module Vulnerabilities ...@@ -281,12 +281,14 @@ module Vulnerabilities
end end
def evidence def evidence
evidence_data = finding_evidence.present? ? finding_evidence.data : metadata.dig('evidence')
{ {
summary: metadata.dig('evidence', 'summary'), summary: evidence_data&.dig('summary'),
request: build_evidence_request(metadata.dig('evidence', 'request')), request: build_evidence_request(evidence_data&.dig('request')),
response: build_evidence_response(metadata.dig('evidence', 'response')), response: build_evidence_response(evidence_data&.dig('response')),
source: build_evidence_source(metadata.dig('evidence', 'source')), source: build_evidence_source(evidence_data&.dig('source')),
supporting_messages: build_evidence_supporting_messages(metadata.dig('evidence', 'supporting_messages')) supporting_messages: build_evidence_supporting_messages(evidence_data&.dig('supporting_messages'))
} }
end end
......
...@@ -7,7 +7,7 @@ module Vulnerabilities ...@@ -7,7 +7,7 @@ module Vulnerabilities
belongs_to :finding, belongs_to :finding,
class_name: 'Vulnerabilities::Finding', class_name: 'Vulnerabilities::Finding',
inverse_of: :evidence, inverse_of: :finding_evidence,
foreign_key: 'vulnerability_occurrence_id', foreign_key: 'vulnerability_occurrence_id',
optional: false optional: false
......
...@@ -2,6 +2,55 @@ ...@@ -2,6 +2,55 @@
FactoryBot.define do FactoryBot.define do
factory :vulnerabilties_finding_evidence, class: 'Vulnerabilities::Finding::Evidence' do factory :vulnerabilties_finding_evidence, class: 'Vulnerabilities::Finding::Evidence' do
finding { association :vulnerabilities_finding }
summary { 'Evidence summary' } summary { 'Evidence summary' }
data do
{
summary: 'Credit card detected',
request: {
headers: [{ name: 'Accept', value: '*/*' }],
method: 'GET',
url: 'http://goat:8080/WebGoat/logout',
body: nil
},
response: {
headers: [{ name: 'Content-Length', value: '0' }],
reason_phrase: 'OK',
status_code: 200,
body: nil
},
source: {
id: 'assert:Response Body Analysis',
name: 'Response Body Analysis',
url: 'htpp://hostname/documentation'
},
supporting_messages: [
{
name: 'Origional',
request: {
headers: [{ name: 'Accept', value: '*/*' }],
method: 'GET',
url: 'http://goat:8080/WebGoat/logout',
body: ''
}
},
{
name: 'Recorded',
request: {
headers: [{ name: 'Accept', value: '*/*' }],
method: 'GET',
url: 'http://goat:8080/WebGoat/logout',
body: ''
},
response: {
headers: [{ name: 'Content-Length', value: '0' }],
reason_phrase: 'OK',
status_code: 200,
body: ''
}
}
]
}
end
end end
end end
...@@ -25,7 +25,7 @@ RSpec.describe Vulnerabilities::Finding do ...@@ -25,7 +25,7 @@ RSpec.describe Vulnerabilities::Finding do
it { is_expected.to have_many(:finding_remediations).class_name('Vulnerabilities::FindingRemediation').with_foreign_key('vulnerability_occurrence_id') } it { is_expected.to have_many(:finding_remediations).class_name('Vulnerabilities::FindingRemediation').with_foreign_key('vulnerability_occurrence_id') }
it { is_expected.to have_many(:vulnerability_flags).class_name('Vulnerabilities::Flag').with_foreign_key('vulnerability_occurrence_id') } it { is_expected.to have_many(:vulnerability_flags).class_name('Vulnerabilities::Flag').with_foreign_key('vulnerability_occurrence_id') }
it { is_expected.to have_many(:remediations).through(:finding_remediations) } it { is_expected.to have_many(:remediations).through(:finding_remediations) }
it { is_expected.to have_one(:evidence).class_name('Vulnerabilities::Finding::Evidence').with_foreign_key('vulnerability_occurrence_id') } it { is_expected.to have_one(:finding_evidence).class_name('Vulnerabilities::Finding::Evidence').with_foreign_key('vulnerability_occurrence_id') }
end end
describe 'validations' do describe 'validations' do
...@@ -751,79 +751,87 @@ RSpec.describe Vulnerabilities::Finding do ...@@ -751,79 +751,87 @@ RSpec.describe Vulnerabilities::Finding do
describe '#evidence' do describe '#evidence' do
subject { finding.evidence } subject { finding.evidence }
context 'has an evidence fields' do shared_examples 'evidence schema' do
let(:finding) { create(:vulnerabilities_finding) } it 'matches evidence schema' do
let(:evidence) { finding.metadata['evidence'] } example_evidence = evidence.with_indifferent_access
is_expected.to match a_hash_including(
summary: example_evidence['summary']
)
it do
is_expected.to match a_hash_including( is_expected.to match a_hash_including(
summary: evidence['summary'],
request: { request: {
headers: [ headers: [
{ {
name: evidence['request']['headers'][0]['name'], name: example_evidence['request']['headers'][0]['name'],
value: evidence['request']['headers'][0]['value'] value: example_evidence['request']['headers'][0]['value']
} }
], ],
url: evidence['request']['url'], url: example_evidence['request']['url'],
method: evidence['request']['method'], method: example_evidence['request']['method'],
body: evidence['request']['body'] body: example_evidence['request']['body']
}, }
)
is_expected.to match a_hash_including(
response: { response: {
headers: [ headers: [
{ {
name: evidence['response']['headers'][0]['name'], name: example_evidence['response']['headers'][0]['name'],
value: evidence['response']['headers'][0]['value'] value: example_evidence['response']['headers'][0]['value']
} }
], ],
reason_phrase: evidence['response']['reason_phrase'], reason_phrase: example_evidence['response']['reason_phrase'],
status_code: evidence['response']['status_code'], status_code: example_evidence['response']['status_code'],
body: evidence['request']['body'] body: example_evidence['request']['body']
}, },
source: { source: {
id: evidence.dig('source', 'id'), id: example_evidence.dig('source', 'id'),
name: evidence.dig('source', 'name'), name: example_evidence.dig('source', 'name'),
url: evidence.dig('source', 'url') url: example_evidence.dig('source', 'url')
}, }
)
is_expected.to match a_hash_including(
supporting_messages: [ supporting_messages: [
{ {
name: evidence.dig('supporting_messages')[0].dig('name'), name: example_evidence.dig('supporting_messages')[0].dig('name'),
request: { request: {
headers: [ headers: [
{ {
name: evidence.dig('supporting_messages')[0].dig('request', 'headers')[0].dig('name'), name: example_evidence.dig('supporting_messages')[0].dig('request', 'headers')[0].dig('name'),
value: evidence.dig('supporting_messages')[0].dig('request', 'headers')[0].dig('value') value: example_evidence.dig('supporting_messages')[0].dig('request', 'headers')[0].dig('value')
} }
], ],
url: evidence.dig('supporting_messages')[0].dig('request', 'url'), url: example_evidence.dig('supporting_messages')[0].dig('request', 'url'),
method: evidence.dig('supporting_messages')[0].dig('request', 'method'), method: example_evidence.dig('supporting_messages')[0].dig('request', 'method'),
body: evidence.dig('supporting_messages')[0].dig('request', 'body') body: example_evidence.dig('supporting_messages')[0].dig('request', 'body')
}, },
response: evidence.dig('supporting_messages')[0].dig('response') response: example_evidence.dig('supporting_messages')[0].dig('response')
}, },
{ {
name: evidence.dig('supporting_messages')[1].dig('name'), name: example_evidence.dig('supporting_messages')[1].dig('name'),
request: { request: {
headers: [ headers: [
{ {
name: evidence.dig('supporting_messages')[1].dig('request', 'headers')[0].dig('name'), name: example_evidence.dig('supporting_messages')[1].dig('request', 'headers')[0].dig('name'),
value: evidence.dig('supporting_messages')[1].dig('request', 'headers')[0].dig('value') value: example_evidence.dig('supporting_messages')[1].dig('request', 'headers')[0].dig('value')
} }
], ],
url: evidence.dig('supporting_messages')[1].dig('request', 'url'), url: example_evidence.dig('supporting_messages')[1].dig('request', 'url'),
method: evidence.dig('supporting_messages')[1].dig('request', 'method'), method: example_evidence.dig('supporting_messages')[1].dig('request', 'method'),
body: evidence.dig('supporting_messages')[1].dig('request', 'body') body: example_evidence.dig('supporting_messages')[1].dig('request', 'body')
}, },
response: { response: {
headers: [ headers: [
{ {
name: evidence.dig('supporting_messages')[1].dig('response', 'headers')[0].dig('name'), name: example_evidence.dig('supporting_messages')[1].dig('response', 'headers')[0].dig('name'),
value: evidence.dig('supporting_messages')[1].dig('response', 'headers')[0].dig('value') value: example_evidence.dig('supporting_messages')[1].dig('response', 'headers')[0].dig('value')
} }
], ],
reason_phrase: evidence.dig('supporting_messages')[1].dig('response', 'reason_phrase'), reason_phrase: example_evidence.dig('supporting_messages')[1].dig('response', 'reason_phrase'),
status_code: evidence.dig('supporting_messages')[1].dig('response', 'status_code'), status_code: example_evidence.dig('supporting_messages')[1].dig('response', 'status_code'),
body: evidence.dig('supporting_messages')[1].dig('response', 'body') body: example_evidence.dig('supporting_messages')[1].dig('response', 'body')
} }
} }
] ]
...@@ -831,6 +839,14 @@ RSpec.describe Vulnerabilities::Finding do ...@@ -831,6 +839,14 @@ RSpec.describe Vulnerabilities::Finding do
end end
end end
context 'without finding_evidence' do
context 'has an evidence fields' do
let(:finding) { create(:vulnerabilities_finding) }
let(:evidence) { finding.metadata['evidence'] }
include_examples 'evidence schema'
end
context 'has no evidence summary when evidence is present, summary is not' do context 'has no evidence summary when evidence is present, summary is not' do
let(:finding) { create(:vulnerabilities_finding, raw_metadata: { evidence: {} }) } let(:finding) { create(:vulnerabilities_finding, raw_metadata: { evidence: {} }) }
...@@ -845,6 +861,15 @@ RSpec.describe Vulnerabilities::Finding do ...@@ -845,6 +861,15 @@ RSpec.describe Vulnerabilities::Finding do
end end
end end
context 'with finding_evidence' do
let(:finding_evidence) { build(:vulnerabilties_finding_evidence) }
let(:finding) { finding_evidence.finding }
let(:evidence) { finding_evidence.data }
include_examples 'evidence schema'
end
end
describe '#message' do describe '#message' do
let(:finding) { build(:vulnerabilities_finding) } let(:finding) { build(:vulnerabilities_finding) }
let(:expected_message) { finding.metadata['message'] } let(:expected_message) { finding.metadata['message'] }
......
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