Commit dea7a7ef authored by James Lopez's avatar James Lopez

Merge branch '260432-add-new-schema-fields-api-fuzzing' into 'master'

Add new DAST schema fields to backend for API Fuzzing

See merge request gitlab-org/gitlab!44800
parents 56100117 f4e84c57
......@@ -65,7 +65,10 @@ module VulnerabilitiesHelper
:scanner,
:solution,
:request,
:response
:response,
:evidence_source,
:supporting_messages,
:assets
)
if data[:location]['file']
......
......@@ -263,19 +263,67 @@ module Vulnerabilities
metadata.dig('remediations')
end
def build_evidence_request(data)
return if data.nil?
{
headers: data.fetch('headers', []).map do |request_header|
{
name: request_header['name'],
value: request_header['value']
}
end,
method: data['method'],
url: data['url'],
body: data['body']
}
end
def build_evidence_response(data)
return if data.nil?
{
headers: data.fetch('headers', []).map do |header_data|
{
name: header_data['name'],
value: header_data['value']
}
end,
status_code: data['status_code'],
reason_phrase: data['reason_phrase'],
body: data['body']
}
end
def build_evidence_supporting_messages(data)
return [] if data.nil?
data.map do |message|
{
name: message['name'],
request: build_evidence_request(message['request']),
response: build_evidence_response(message['response'])
}
end
end
def build_evidence_source(data)
return if data.nil?
{
id: data['id'],
name: data['name'],
url: data['url']
}
end
def evidence
{
summary: metadata.dig('evidence', 'summary'),
request: {
headers: metadata.dig('evidence', 'request', 'headers') || [],
method: metadata.dig('evidence', 'request', 'method'),
url: metadata.dig('evidence', 'request', 'url')
},
response: {
headers: metadata.dig('evidence', 'response', 'headers') || [],
status_code: metadata.dig('evidence', 'response', 'status_code'),
reason_phrase: metadata.dig('evidence', 'response', 'reason_phrase')
}
request: build_evidence_request(metadata.dig('evidence', 'request')),
response: build_evidence_response(metadata.dig('evidence', 'response')),
source: build_evidence_source(metadata.dig('evidence', 'source')),
supporting_messages: build_evidence_supporting_messages(metadata.dig('evidence', 'supporting_messages'))
}
end
......@@ -295,6 +343,16 @@ module Vulnerabilities
identifiers.select(&:other?).map(&:name)
end
def assets
metadata.fetch('assets', []).map do |asset_data|
{
name: asset_data['name'],
type: asset_data['type'],
url: asset_data['url']
}
end
end
alias_method :==, :eql? # eql? is necessary in some cases like array intersection
def eql?(other)
......
......@@ -31,6 +31,9 @@ class Vulnerabilities::FindingEntity < Grape::Entity
expose(:evidence) { |model, _| model.evidence[:summary] }
expose(:request, using: Vulnerabilities::RequestEntity) { |model, _| model.evidence[:request] }
expose(:response, using: Vulnerabilities::ResponseEntity) { |model, _| model.evidence[:response] }
expose(:evidence_source) { |model, _| model.evidence[:source] }
expose(:supporting_messages) { |model, _| model.evidence[:supporting_messages]}
expose(:assets) { |model, _| model.assets }
end
expose :state
......
......@@ -4,4 +4,5 @@ class Vulnerabilities::RequestEntity < Grape::Entity
expose :headers
expose :method
expose :url
expose :body
end
......@@ -4,4 +4,5 @@ class Vulnerabilities::ResponseEntity < Grape::Entity
expose :headers
expose :reason_phrase
expose :status_code
expose :body
end
---
title: Add new security report schema fields to backend for API Fuzzing
merge_request: 44800
author:
type: changed
......@@ -56,18 +56,58 @@ FactoryBot.define do
url: 'https://crypto.stackexchange.com/questions/31428/pbewithmd5anddes-cipher-does-not-check-for-integrity-first'
}
],
assets: [
{
type: "postman",
name: "Test Postman Collection",
url: "http://localhost/test.collection"
}
],
evidence: {
summary: 'Credit card detected',
request: {
headers: [{ name: 'Accept', value: '*/*' }],
method: 'GET',
url: 'http://goat:8080/WebGoat/logout'
url: 'http://goat:8080/WebGoat/logout',
body: nil
},
response: {
headers: [{ name: 'Content-Length', value: '0' }],
reason_phrase: 'OK',
status_code: 200
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: ''
}
}
]
}
}.to_json
end
......
......@@ -161,7 +161,10 @@ RSpec.describe VulnerabilitiesHelper do
evidence: kind_of(String),
scanner: kind_of(Grape::Entity::Exposure::NestingExposure::OutputBuilder),
request: kind_of(Grape::Entity::Exposure::NestingExposure::OutputBuilder),
response: kind_of(Grape::Entity::Exposure::NestingExposure::OutputBuilder)
response: kind_of(Grape::Entity::Exposure::NestingExposure::OutputBuilder),
evidence_source: anything,
assets: kind_of(Array),
supporting_messages: kind_of(Array)
)
expect(subject[:location]['blob_path']).to match(kind_of(String))
......
......@@ -628,15 +628,75 @@ RSpec.describe Vulnerabilities::Finding do
is_expected.to match a_hash_including(
summary: evidence['summary'],
request: {
headers: evidence['request']['headers'],
headers: [
{
name: evidence['request']['headers'][0]['name'],
value: evidence['request']['headers'][0]['value']
}
],
url: evidence['request']['url'],
method: evidence['request']['method']
method: evidence['request']['method'],
body: evidence['request']['body']
},
response: {
headers: evidence['response']['headers'],
headers: [
{
name: evidence['response']['headers'][0]['name'],
value: evidence['response']['headers'][0]['value']
}
],
reason_phrase: evidence['response']['reason_phrase'],
status_code: evidence['response']['status_code']
})
status_code: evidence['response']['status_code'],
body: evidence['request']['body']
},
source: {
id: evidence.dig('source', 'id'),
name: evidence.dig('source', 'name'),
url: evidence.dig('source', 'url')
},
supporting_messages: [
{
name: evidence.dig('supporting_messages')[0].dig('name'),
request: {
headers: [
{
name: evidence.dig('supporting_messages')[0].dig('request', 'headers')[0].dig('name'),
value: evidence.dig('supporting_messages')[0].dig('request', 'headers')[0].dig('value')
}
],
url: evidence.dig('supporting_messages')[0].dig('request', 'url'),
method: evidence.dig('supporting_messages')[0].dig('request', 'method'),
body: evidence.dig('supporting_messages')[0].dig('request', 'body')
},
response: evidence.dig('supporting_messages')[0].dig('response')
},
{
name: evidence.dig('supporting_messages')[1].dig('name'),
request: {
headers: [
{
name: evidence.dig('supporting_messages')[1].dig('request', 'headers')[0].dig('name'),
value: evidence.dig('supporting_messages')[1].dig('request', 'headers')[0].dig('value')
}
],
url: evidence.dig('supporting_messages')[1].dig('request', 'url'),
method: evidence.dig('supporting_messages')[1].dig('request', 'method'),
body: evidence.dig('supporting_messages')[1].dig('request', 'body')
},
response: {
headers: [
{
name: evidence.dig('supporting_messages')[1].dig('response', 'headers')[0].dig('name'),
value: evidence.dig('supporting_messages')[1].dig('response', 'headers')[0].dig('value')
}
],
reason_phrase: evidence.dig('supporting_messages')[1].dig('response', 'reason_phrase'),
status_code: evidence.dig('supporting_messages')[1].dig('response', 'status_code'),
body: evidence.dig('supporting_messages')[1].dig('response', 'body')
}
}
]
)
end
end
......@@ -646,16 +706,10 @@ RSpec.describe Vulnerabilities::Finding do
it do
is_expected.to match a_hash_including(
summary: nil,
request: {
headers: [],
url: nil,
method: nil
},
response: {
headers: [],
reason_phrase: nil,
status_code: nil
})
source: nil,
supporting_messages: [],
request: nil,
response: nil)
end
end
end
......
......@@ -58,6 +58,7 @@ RSpec.describe Vulnerabilities::FindingEntity do
expect(subject).to include(:description, :links, :location, :remediations, :solution, :evidence)
expect(subject).to include(:blob_path, :request, :response)
expect(subject).to include(:scan)
expect(subject).to include(:assets, :evidence_source, :supporting_messages)
end
context 'when not allowed to admin vulnerability feedback' do
......
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