Commit 37a92bfa authored by Alan (Maciej) Paruszewski's avatar Alan (Maciej) Paruszewski Committed by Mayra Cabrera

Add parsing vendor name from security reports

This change adds ability to parse new version of Security Report with
Vendor object.
parent cded1bcd
......@@ -11,7 +11,7 @@ module Vulnerabilities
validates :project, presence: true
validates :external_id, presence: true, uniqueness: { scope: :project_id }
validates :name, presence: true
validates :vendor, presence: true, length: { maximum: 255 }
validates :vendor, length: { maximum: 255, allow_nil: false }
scope :with_external_id, -> (external_ids) { where(external_id: external_ids) }
end
......
---
title: Add parsing Vendor name from Security Reports
merge_request: 35222
author:
type: added
......@@ -72,7 +72,8 @@ module Gitlab
report.add_scanner(
::Gitlab::Ci::Reports::Security::Scanner.new(
external_id: scanner['id'],
name: scanner['name']))
name: scanner['name'],
vendor: scanner.dig('vendor', 'name')))
end
def create_identifiers(report, identifiers)
......
......@@ -61,7 +61,7 @@ module Gitlab
'severity' => severity(vulnerability['riskcode']),
'solution' => sanitize(vulnerability['solution']),
'confidence' => confidence(vulnerability['confidence']),
'scanner' => { 'id' => 'zaproxy', 'name' => 'ZAProxy' },
'scanner' => { 'id' => 'zaproxy', 'name' => 'ZAProxy', 'vendor' => { 'name' => 'GitLab' } },
'identifiers' => [
{
'type' => 'ZAProxy_PluginId',
......
......@@ -5,11 +5,12 @@ module Gitlab
module Reports
module Security
class Scanner
attr_accessor :external_id, :name
attr_accessor :external_id, :name, :vendor
def initialize(external_id:, name:)
def initialize(external_id:, name:, vendor:)
@external_id = external_id
@name = name
@vendor = vendor
end
def key
......@@ -20,8 +21,9 @@ module Gitlab
%i[
external_id
name
vendor
].each_with_object({}) do |key, hash|
hash[key] = public_send(key) # rubocop:disable GitlabSecurity/PublicSend
hash[key] = public_send(key).to_s # rubocop:disable GitlabSecurity/PublicSend
end
end
......
......@@ -4,6 +4,7 @@ FactoryBot.define do
factory :ci_reports_security_scanner, class: '::Gitlab::Ci::Reports::Security::Scanner' do
external_id { 'find_sec_bugs' }
name { 'Find Security Bugs' }
vendor { 'Security Scanner Vendor' }
skip_create
......
......@@ -36,7 +36,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
"cve": "CVE-1020",
"severity": "High",
"solution": "Upgrade to latest version.",
"scanner": { "id": "gemnasium", "name": "Gemnasium" },
"scanner": { "id": "gemnasium", "name": "Gemnasium", "vendor": { "name": "GitLab" } },
"location": {},
"identifiers": [],
"links": [{ "url": "" }]
......@@ -52,7 +52,8 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
"solution": "Upgrade to latest versions.",
"scanner": {
"id": "gemnasium",
"name": "Gemnasium"
"name": "Gemnasium",
"vendor": { "name": "GitLab" }
},
"location": {},
"identifiers": [],
......@@ -68,7 +69,8 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
"solution": "Upgrade to fixed version.\r\n",
"scanner": {
"id": "gemnasium",
"name": "Gemnasium"
"name": "Gemnasium",
"vendor": { "name": "GitLab" }
},
"location": {},
"identifiers": [],
......@@ -177,5 +179,51 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
end
end
end
context 'parsing scanners' do
let(:raw_json) do
{
"vulnerabilities": [
{
"category": "dependency_scanning",
"name": "Vulnerabilities in libxml2",
"message": "Vulnerabilities in libxml2 in nokogiri",
"description": "",
"cve": "CVE-1020",
"severity": "High",
"solution": "Upgrade to latest version.",
"scanner": raw_scanner,
"location": {},
"identifiers": [],
"links": [{ "url": "" }]
}
],
"remediations": [],
"dependency_files": []
}
end
subject(:scanner) { report.occurrences.first.scanner }
before do
parser.parse!(raw_json.to_json, report)
end
context 'when vendor is missing in scanner' do
let(:raw_scanner) { { 'id': 'gemnasium', 'name': 'Gemnasium' } }
it 'returns scanner with empty vendor field' do
expect(scanner.vendor).to be_nil
end
end
context 'when vendor is not missing in scanner' do
let(:raw_scanner) { { 'id': 'gemnasium', 'name': 'Gemnasium', 'vendor': { 'name': 'GitLab' } } }
it 'returns scanner with parsed vendor value' do
expect(scanner.vendor).to eq('GitLab')
end
end
end
end
end
......@@ -33,7 +33,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Formatters::Dast do
expect(vulnerability['severity']).to eq('high')
expect(vulnerability['confidence']).to eq('medium')
expect(vulnerability['solution']).to eq(sanitized_solution)
expect(vulnerability['scanner']).to eq({ 'id' => 'zaproxy', 'name' => 'ZAProxy' })
expect(vulnerability['scanner']).to eq({ 'id' => 'zaproxy', 'name' => 'ZAProxy', 'vendor' => { 'name' => 'GitLab' } })
expect(vulnerability['links']).to eq([{ 'url' => 'http://projects.webappsec.org/Cross-Site-Request-Forgery' },
{ 'url' => 'http://cwe.mitre.org/data/definitions/352.html' }])
expect(vulnerability['identifiers'][0]).to eq({
......
......@@ -9,7 +9,8 @@ RSpec.describe Gitlab::Ci::Reports::Security::Scanner do
let(:params) do
{
external_id: 'brakeman',
name: 'Brakeman'
name: 'Brakeman',
vendor: 'GitLab'
}
end
......@@ -19,7 +20,8 @@ RSpec.describe Gitlab::Ci::Reports::Security::Scanner do
expect(subject).to have_attributes(
external_id: 'brakeman',
name: 'Brakeman'
name: 'Brakeman',
vendor: 'GitLab'
)
end
end
......@@ -55,7 +57,8 @@ RSpec.describe Gitlab::Ci::Reports::Security::Scanner do
it 'returns expected hash' do
is_expected.to eq({
external_id: scanner.external_id,
name: scanner.name
name: scanner.name,
vendor: scanner.vendor
})
end
end
......
......@@ -15,7 +15,6 @@ RSpec.describe Vulnerabilities::Scanner do
it { is_expected.to validate_presence_of(:project) }
it { is_expected.to validate_presence_of(:external_id) }
it { is_expected.to validate_uniqueness_of(:external_id).scoped_to(:project_id) }
it { is_expected.to validate_presence_of(:vendor) }
it { is_expected.to validate_length_of(:vendor).is_at_most(255) }
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