Commit 0cf10248 authored by Alan (Maciej) Paruszewski's avatar Alan (Maciej) Paruszewski Committed by Dylan Griffith

Add filtering by scanner ID in Vulnerability Occurrences REST API

parent a31e72db
...@@ -43,6 +43,7 @@ GET /projects/:id/vulnerability_findings?scope=all ...@@ -43,6 +43,7 @@ GET /projects/:id/vulnerability_findings?scope=all
GET /projects/:id/vulnerability_findings?scope=dismissed GET /projects/:id/vulnerability_findings?scope=dismissed
GET /projects/:id/vulnerability_findings?severity=high GET /projects/:id/vulnerability_findings?severity=high
GET /projects/:id/vulnerability_findings?confidence=unknown,experimental GET /projects/:id/vulnerability_findings?confidence=unknown,experimental
GET /projects/:id/vulnerability_findings?scanner=bandit,find_sec_bugs
GET /projects/:id/vulnerability_findings?pipeline_id=42 GET /projects/:id/vulnerability_findings?pipeline_id=42
``` ```
...@@ -56,6 +57,7 @@ Beginning with GitLab 12.9, the `undefined` severity and confidence level is no ...@@ -56,6 +57,7 @@ Beginning with GitLab 12.9, the `undefined` severity and confidence level is no
| `scope` | string | no | Returns vulnerability findings for the given scope: `all` or `dismissed`. Defaults to `dismissed`. | | `scope` | string | no | Returns vulnerability findings for the given scope: `all` or `dismissed`. Defaults to `dismissed`. |
| `severity` | string array | no | Returns vulnerability findings belonging to specified severity level: `info`, `unknown`, `low`, `medium`, `high`, or `critical`. Defaults to all. | | `severity` | string array | no | Returns vulnerability findings belonging to specified severity level: `info`, `unknown`, `low`, `medium`, `high`, or `critical`. Defaults to all. |
| `confidence` | string array | no | Returns vulnerability findings belonging to specified confidence level: `ignore`, `unknown`, `experimental`, `low`, `medium`, `high`, or `confirmed`. Defaults to all. | | `confidence` | string array | no | Returns vulnerability findings belonging to specified confidence level: `ignore`, `unknown`, `experimental`, `low`, `medium`, `high`, or `confirmed`. Defaults to all. |
| `scanner` | string array | no | Returns vulnerability findings detected by specified scanner.
| `pipeline_id` | integer/string | no | Returns vulnerability findings belonging to specified pipeline. | | `pipeline_id` | integer/string | no | Returns vulnerability findings belonging to specified pipeline. |
```shell ```shell
......
...@@ -103,6 +103,7 @@ module Security ...@@ -103,6 +103,7 @@ module Security
next if !include_dismissed? && dismissal_feedback?(occurrence) next if !include_dismissed? && dismissal_feedback?(occurrence)
next unless confidence_levels.include?(occurrence.confidence) next unless confidence_levels.include?(occurrence.confidence)
next unless severity_levels.include?(occurrence.severity) next unless severity_levels.include?(occurrence.severity)
next if scanners.present? && !scanners.include?(occurrence.scanner.external_id)
occurrence occurrence
end end
...@@ -140,5 +141,9 @@ module Security ...@@ -140,5 +141,9 @@ module Security
def severity_levels def severity_levels
Array(params.fetch(:severity, Vulnerabilities::Occurrence.severities.keys)) Array(params.fetch(:severity, Vulnerabilities::Occurrence.severities.keys))
end end
def scanners
Array(params.fetch(:scanner, []))
end
end end
end end
---
title: Add filtering by scanner ID in Vulnerability Occurrences REST API
merge_request: 36241
author:
type: added
...@@ -55,6 +55,10 @@ module API ...@@ -55,6 +55,10 @@ module API
'Defaults to all', 'Defaults to all',
values: ::Vulnerabilities::Occurrence.confidences.keys, values: ::Vulnerabilities::Occurrence.confidences.keys,
default: ::Vulnerabilities::Occurrence.confidences.keys default: ::Vulnerabilities::Occurrence.confidences.keys
optional :scanner,
type: Array[String],
coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce,
desc: 'Returns vulnerabilities detected by specified scanners'
optional :pipeline_id, type: String, desc: 'The ID of the pipeline' optional :pipeline_id, type: String, desc: 'The ID of the pipeline'
use :pagination use :pagination
......
...@@ -207,12 +207,31 @@ RSpec.describe Security::PipelineVulnerabilitiesFinder do ...@@ -207,12 +207,31 @@ RSpec.describe Security::PipelineVulnerabilitiesFinder do
end end
end end
context 'by scanner' do
context 'when unscoped' do
subject { described_class.new(pipeline: pipeline).execute }
it 'returns all vulnerabilities with all scanners available' do
expect(subject.occurrences.map(&:scanner).map(&:external_id).uniq).to match_array %w[bandit bundler_audit find_sec_bugs flawfinder gemnasium klar zaproxy]
end
end
context 'when `zaproxy`' do
subject { described_class.new(pipeline: pipeline, params: { scanner: 'zaproxy' } ).execute }
it 'returns only vulnerabilities with selected scanner external id' do
expect(subject.occurrences.map(&:scanner).map(&:external_id).uniq).to match_array(%w[zaproxy])
end
end
end
context 'by all filters' do context 'by all filters' do
context 'with found entity' do context 'with found entity' do
let(:params) { { report_type: %w[sast dast container_scanning dependency_scanning], scope: 'all' } } let(:params) { { report_type: %w[sast dast container_scanning dependency_scanning], scanner: %w[bandit bundler_audit find_sec_bugs flawfinder gemnasium klar zaproxy], scope: 'all' } }
it 'filters by all params' do it 'filters by all params' do
expect(subject.occurrences.count).to eq(cs_count + dast_count + ds_count + sast_count) expect(subject.occurrences.count).to eq(cs_count + dast_count + ds_count + sast_count)
expect(subject.occurrences.map(&:scanner).map(&:external_id).uniq).to match_array %w[bandit bundler_audit find_sec_bugs flawfinder gemnasium klar zaproxy]
expect(subject.occurrences.map(&:confidence).uniq).to match_array(%w[unknown low medium high]) expect(subject.occurrences.map(&:confidence).uniq).to match_array(%w[unknown low medium high])
expect(subject.occurrences.map(&:severity).uniq).to match_array(%w[unknown low medium high critical info]) expect(subject.occurrences.map(&:severity).uniq).to match_array(%w[unknown low medium high critical info])
end end
......
...@@ -149,6 +149,14 @@ RSpec.describe API::VulnerabilityFindings do ...@@ -149,6 +149,14 @@ RSpec.describe API::VulnerabilityFindings do
expect(response).to have_gitlab_http_status(:bad_request) expect(response).to have_gitlab_http_status(:bad_request)
end end
it 'returns vulnerabilities detected by bandit and find_sec_bugs scanners' do
get api(project_vulnerability_findings_path, user), params: { scanner: 'bandit,find_sec_bugs' }.merge(pagination)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response.map { |v| v.dig('scanner', 'external_id') }.uniq).to match_array %w[bandit find_sec_bugs]
end
context 'when pipeline_id is supplied' do context 'when pipeline_id is supplied' do
it 'returns vulnerabilities from supplied pipeline' do it 'returns vulnerabilities from supplied pipeline' do
occurrence_count = (sast_report.occurrences.count + ds_report.occurrences.count - 1).to_s occurrence_count = (sast_report.occurrences.count + ds_report.occurrences.count - 1).to_s
......
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