Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
19ae43b3
Commit
19ae43b3
authored
May 12, 2020
by
Adam Cohen
Committed by
charlie ablett
May 12, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove deprecated container scanning report parser
parent
a91546fe
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
284 additions
and
720 deletions
+284
-720
changelogs/unreleased/remove-deprecated-container-scanning-report-format.yml
...ed/remove-deprecated-container-scanning-report-format.yml
+5
-0
ee/lib/gitlab/ci/parsers/security/container_scanning.rb
ee/lib/gitlab/ci/parsers/security/container_scanning.rb
+0
-33
ee/lib/gitlab/ci/parsers/security/formatters/deprecated_container_scanning.rb
...sers/security/formatters/deprecated_container_scanning.rb
+0
-57
ee/lib/gitlab/ci/parsers/security/formatters/deprecated_formatted_container_scanning_vulnerability.rb
.../deprecated_formatted_container_scanning_vulnerability.rb
+0
-100
ee/spec/factories/ci/builds.rb
ee/spec/factories/ci/builds.rb
+0
-6
ee/spec/factories/ci/job_artifacts.rb
ee/spec/factories/ci/job_artifacts.rb
+0
-10
ee/spec/finders/security/pipeline_vulnerabilities_finder_spec.rb
.../finders/security/pipeline_vulnerabilities_finder_spec.rb
+217
-231
ee/spec/fixtures/security_reports/feature-branch/gl-container-scanning-report.json
..._reports/feature-branch/gl-container-scanning-report.json
+38
-11
ee/spec/lib/gitlab/ci/parsers/security/container_scanning_spec.rb
...lib/gitlab/ci/parsers/security/container_scanning_spec.rb
+24
-32
ee/spec/lib/gitlab/ci/parsers/security/formatters/deprecated_container_scanning_spec.rb
...security/formatters/deprecated_container_scanning_spec.rb
+0
-51
ee/spec/lib/gitlab/ci/parsers/security/formatters/deprecated_formatted_container_scanning_vulnerability_spec.rb
...ecated_formatted_container_scanning_vulnerability_spec.rb
+0
-189
No files found.
changelogs/unreleased/remove-deprecated-container-scanning-report-format.yml
0 → 100644
View file @
19ae43b3
---
title
:
Remove deprecated container scanning report parser
merge_request
:
31294
author
:
type
:
removed
ee/lib/gitlab/ci/parsers/security/container_scanning.rb
View file @
19ae43b3
...
@@ -5,41 +5,8 @@ module Gitlab
...
@@ -5,41 +5,8 @@ module Gitlab
module
Parsers
module
Parsers
module
Security
module
Security
class
ContainerScanning
<
Common
class
ContainerScanning
<
Common
include
Security
::
Concerns
::
DeprecatedSyntax
DEPRECATED_REPORT_VERSION
=
"1.3"
.
freeze
def
parse_report
(
json_data
)
report
=
super
return
format_deprecated_report
(
report
)
if
deprecated?
(
report
)
report
end
private
private
# Transforms the clair-scanner JSON report into the expected format
# TODO: remove the following block when we no longer need to support legacy
# clair-scanner data. See https://gitlab.com/gitlab-org/gitlab/issues/35442
def
format_deprecated_report
(
data
)
unapproved
=
data
[
'unapproved'
]
formatter
=
Formatters
::
DeprecatedContainerScanning
.
new
(
data
[
'image'
])
vulnerabilities
=
data
[
'vulnerabilities'
].
map
do
|
vulnerability
|
# We only report unapproved vulnerabilities
next
unless
unapproved
.
include?
(
vulnerability
[
'vulnerability'
])
formatter
.
format
(
vulnerability
)
end
.
compact
{
"vulnerabilities"
=>
vulnerabilities
,
"version"
=>
DEPRECATED_REPORT_VERSION
}
end
def
deprecated?
(
data
)
data
[
'image'
]
end
def
create_location
(
location_data
)
def
create_location
(
location_data
)
::
Gitlab
::
Ci
::
Reports
::
Security
::
Locations
::
ContainerScanning
.
new
(
::
Gitlab
::
Ci
::
Reports
::
Security
::
Locations
::
ContainerScanning
.
new
(
image:
location_data
[
'image'
],
image:
location_data
[
'image'
],
...
...
ee/lib/gitlab/ci/parsers/security/formatters/deprecated_container_scanning.rb
deleted
100644 → 0
View file @
a91546fe
# frozen_string_literal: true
# TODO: remove this class when we no longer need to support legacy
# clair-scanner data. See https://gitlab.com/gitlab-org/gitlab/issues/35442
module
Gitlab
module
Ci
module
Parsers
module
Security
module
Formatters
class
DeprecatedContainerScanning
def
initialize
(
image
)
@image
=
image
end
def
format
(
vulnerability
)
formatted_vulnerability
=
DeprecatedFormattedContainerScanningVulnerability
.
new
(
vulnerability
)
{
'category'
=>
'container_scanning'
,
'message'
=>
formatted_vulnerability
.
message
,
'description'
=>
formatted_vulnerability
.
description
,
'cve'
=>
formatted_vulnerability
.
cve
,
'severity'
=>
formatted_vulnerability
.
severity
,
'solution'
=>
formatted_vulnerability
.
solution
,
'confidence'
=>
'Unknown'
,
'location'
=>
{
'image'
=>
image
,
'operating_system'
=>
formatted_vulnerability
.
operating_system
,
'dependency'
=>
{
'package'
=>
{
'name'
=>
formatted_vulnerability
.
package_name
},
'version'
=>
formatted_vulnerability
.
version
}
},
'scanner'
=>
{
'id'
=>
'clair'
,
'name'
=>
'Clair'
},
'identifiers'
=>
[
{
'type'
=>
'cve'
,
'name'
=>
formatted_vulnerability
.
cve
,
'value'
=>
formatted_vulnerability
.
cve
,
'url'
=>
formatted_vulnerability
.
url
}
],
'links'
=>
[{
'url'
=>
formatted_vulnerability
.
url
}]
}
end
private
attr_reader
:image
end
end
end
end
end
end
ee/lib/gitlab/ci/parsers/security/formatters/deprecated_formatted_container_scanning_vulnerability.rb
deleted
100644 → 0
View file @
a91546fe
# frozen_string_literal: true
# TODO: remove this class when we no longer need to support legacy
# clair-scanner data. See https://gitlab.com/gitlab-org/gitlab/issues/35442
module
Gitlab
module
Ci
module
Parsers
module
Security
module
Formatters
class
DeprecatedFormattedContainerScanningVulnerability
def
initialize
(
vulnerability
)
@vulnerability
=
vulnerability
end
def
message
@message
||=
format_definitions
(
%w[vulnerability featurename]
=>
'%{vulnerability} in %{featurename}'
,
'vulnerability'
=>
'%{vulnerability}'
)
end
def
description
@description
||=
format_definitions
(
'description'
=>
'%{description}'
,
%w[featurename featureversion]
=>
'%{featurename}:%{featureversion} is affected by %{vulnerability}'
,
'featurename'
=>
'%{featurename} is affected by %{vulnerability}'
,
'namespace'
=>
'%{namespace} is affected by %{vulnerability}'
)
end
def
severity
raw_severity
=
vulnerability
[
'severity'
]
@severity
||=
case
raw_severity
when
'Negligible'
'low'
when
'Unknown'
,
'Low'
,
'Medium'
,
'High'
,
'Critical'
raw_severity
.
downcase
when
'Defcon1'
'critical'
else
safe_severity
=
ERB
::
Util
.
html_escape
(
raw_severity
)
raise
(
::
Gitlab
::
Ci
::
Parsers
::
Security
::
Common
::
SecurityReportParserError
,
"Unknown severity in container scanning report:
#{
safe_severity
}
"
)
end
end
def
solution
@solution
||=
format_definitions
(
%w[fixedby featurename featureversion]
=>
'Upgrade %{featurename} from %{featureversion} to %{fixedby}'
,
%w[fixedby featurename]
=>
'Upgrade %{featurename} to %{fixedby}'
,
'fixedby'
=>
'Upgrade to %{fixedby}'
)
end
def
cve
@cve
||=
vulnerability
[
'vulnerability'
]
end
def
operating_system
@operating_system
||=
vulnerability
[
'namespace'
]
end
def
package_name
@package_name
||=
vulnerability
[
'featurename'
]
end
def
version
@version
||=
vulnerability
[
'featureversion'
]
end
def
url
@url
||=
vulnerability
[
'link'
]
end
private
attr_reader
:vulnerability
def
format_definitions
(
definitions
)
find_definitions
(
definitions
).
then
do
|
_
,
value
|
if
value
.
present?
value
%
vulnerability
.
symbolize_keys
end
end
end
def
find_definitions
(
definitions
)
definitions
.
find
do
|
keys
,
value
|
vulnerability
.
values_at
(
*
keys
).
all?
(
&
:present?
)
end
end
end
end
end
end
end
end
ee/spec/factories/ci/builds.rb
View file @
19ae43b3
...
@@ -72,12 +72,6 @@ FactoryBot.define do
...
@@ -72,12 +72,6 @@ FactoryBot.define do
end
end
end
end
trait
:deprecated_container_scanning_report
do
after
(
:build
)
do
|
build
|
build
.
job_artifacts
<<
create
(
:ee_ci_job_artifact
,
:deprecated_container_scanning_report
,
job:
build
)
end
end
trait
:dependency_scanning_feature_branch
do
trait
:dependency_scanning_feature_branch
do
after
(
:build
)
do
|
build
|
after
(
:build
)
do
|
build
|
build
.
job_artifacts
<<
create
(
:ee_ci_job_artifact
,
:dependency_scanning_feature_branch
,
job:
build
)
build
.
job_artifacts
<<
create
(
:ee_ci_job_artifact
,
:dependency_scanning_feature_branch
,
job:
build
)
...
...
ee/spec/factories/ci/job_artifacts.rb
View file @
19ae43b3
...
@@ -259,16 +259,6 @@ FactoryBot.define do
...
@@ -259,16 +259,6 @@ FactoryBot.define do
end
end
end
end
trait
:deprecated_container_scanning_report
do
file_format
{
:raw
}
file_type
{
:container_scanning
}
after
(
:build
)
do
|
artifact
,
_
|
artifact
.
file
=
fixture_file_upload
(
Rails
.
root
.
join
(
'ee/spec/fixtures/security_reports/deprecated/gl-container-scanning-report.json'
),
'text/plain'
)
end
end
trait
:metrics
do
trait
:metrics
do
file_format
{
:gzip
}
file_format
{
:gzip
}
file_type
{
:metrics
}
file_type
{
:metrics
}
...
...
ee/spec/finders/security/pipeline_vulnerabilities_finder_spec.rb
View file @
19ae43b3
...
@@ -11,310 +11,296 @@ describe Security::PipelineVulnerabilitiesFinder do
...
@@ -11,310 +11,296 @@ describe Security::PipelineVulnerabilitiesFinder do
let_it_be
(
:project
)
{
create
(
:project
,
:repository
)
}
let_it_be
(
:project
)
{
create
(
:project
,
:repository
)
}
let_it_be
(
:pipeline
)
{
create
(
:ci_pipeline
,
:success
,
project:
project
)
}
let_it_be
(
:pipeline
)
{
create
(
:ci_pipeline
,
:success
,
project:
project
)
}
let_it_be
(
:build_cs
)
{
create
(
:ci_build
,
:success
,
name:
'cs_job'
,
pipeline:
pipeline
,
project:
project
)
}
shared_examples_for
'a pipeline vulnerabilities finder'
do
describe
'#execute'
do
let
(
:params
)
{
{}
}
let_it_be
(
:build_dast
)
{
create
(
:ci_build
,
:success
,
name:
'dast_job'
,
pipeline:
pipeline
,
project:
project
)
}
let_it_be
(
:build_ds
)
{
create
(
:ci_build
,
:success
,
name:
'ds_job'
,
pipeline:
pipeline
,
project:
project
)
}
let_it_be
(
:build_sast
)
{
create
(
:ci_build
,
:success
,
name:
'sast_job'
,
pipeline:
pipeline
,
project:
project
)
}
let_it_be
(
:artifact_dast
)
{
create
(
:ee_ci_job_artifact
,
:dast
,
job:
build_dast
,
project:
project
)
}
let_it_be
(
:artifact_ds
)
{
create
(
:ee_ci_job_artifact
,
:dependency_scanning
,
job:
build_ds
,
project:
project
)
}
let_it_be
(
:artifact_sast
)
{
create
(
:ee_ci_job_artifact
,
:sast
,
job:
build_sast
,
project:
project
)
}
let
(
:ds_count
)
{
read_fixture
(
artifact_ds
)[
'vulnerabilities'
].
count
}
let
(
:sast_count
)
{
read_fixture
(
artifact_sast
)[
'vulnerabilities'
].
count
}
let
(
:dast_count
)
do
read_fixture
(
artifact_dast
)[
'site'
].
sum
do
|
site
|
site
[
'alerts'
].
sum
do
|
alert
|
alert
[
'instances'
].
size
end
end
end
before
do
describe
'#execute'
do
stub_licensed_features
(
sast:
true
,
dependency_scanning:
true
,
container_scanning:
true
,
dast:
true
)
let
(
:params
)
{
{}
}
# Stub out deduplication, if not done the expectations will vary based on the fixtures (which may/may not have duplicates)
disable_deduplication
end
subject
{
described_class
.
new
(
pipeline:
pipeline
,
params:
params
).
execute
}
let_it_be
(
:build_cs
)
{
create
(
:ci_build
,
:success
,
name:
'cs_job'
,
pipeline:
pipeline
,
project:
project
)
}
let_it_be
(
:build_dast
)
{
create
(
:ci_build
,
:success
,
name:
'dast_job'
,
pipeline:
pipeline
,
project:
project
)
}
let_it_be
(
:build_ds
)
{
create
(
:ci_build
,
:success
,
name:
'ds_job'
,
pipeline:
pipeline
,
project:
project
)
}
let_it_be
(
:build_sast
)
{
create
(
:ci_build
,
:success
,
name:
'sast_job'
,
pipeline:
pipeline
,
project:
project
)
}
context
'occurrences'
do
let_it_be
(
:artifact_cs
)
{
create
(
:ee_ci_job_artifact
,
:container_scanning
,
job:
build_cs
,
project:
project
)
}
it
'assigns commit sha to findings'
do
let_it_be
(
:artifact_dast
)
{
create
(
:ee_ci_job_artifact
,
:dast
,
job:
build_dast
,
project:
project
)
}
expect
(
subject
.
occurrences
.
map
(
&
:sha
).
uniq
).
to
eq
([
pipeline
.
sha
])
let_it_be
(
:artifact_ds
)
{
create
(
:ee_ci_job_artifact
,
:dependency_scanning
,
job:
build_ds
,
project:
project
)
}
end
let_it_be
(
:artifact_sast
)
{
create
(
:ee_ci_job_artifact
,
:sast
,
job:
build_sast
,
project:
project
)
}
context
'by order'
do
let
(
:cs_count
)
{
read_fixture
(
artifact_cs
)[
'vulnerabilities'
].
count
}
let
(
:params
)
{
{
report_type:
%w[sast]
}
}
let
(
:ds_count
)
{
read_fixture
(
artifact_ds
)[
'vulnerabilities'
].
count
}
let!
(
:high_high
)
{
build
(
:vulnerabilities_occurrence
,
confidence: :high
,
severity: :high
)
}
let
(
:sast_count
)
{
read_fixture
(
artifact_sast
)[
'vulnerabilities'
].
count
}
let!
(
:critical_medium
)
{
build
(
:vulnerabilities_occurrence
,
confidence: :medium
,
severity: :critical
)
}
let
(
:dast_count
)
do
let!
(
:critical_high
)
{
build
(
:vulnerabilities_occurrence
,
confidence: :high
,
severity: :critical
)
}
read_fixture
(
artifact_dast
)[
'site'
].
sum
do
|
site
|
let!
(
:unknown_high
)
{
build
(
:vulnerabilities_occurrence
,
confidence: :high
,
severity: :unknown
)
}
site
[
'alerts'
].
sum
do
|
alert
|
let!
(
:unknown_medium
)
{
build
(
:vulnerabilities_occurrence
,
confidence: :medium
,
severity: :unknown
)
}
alert
[
'instances'
].
size
let!
(
:unknown_low
)
{
build
(
:vulnerabilities_occurrence
,
confidence: :low
,
severity: :unknown
)
}
it
'orders by severity and confidence'
do
allow_next_instance_of
(
described_class
)
do
|
pipeline_vulnerabilities_finder
|
allow
(
pipeline_vulnerabilities_finder
).
to
receive
(
:filter
).
and_return
([
unknown_low
,
unknown_medium
,
critical_high
,
unknown_high
,
critical_medium
,
high_high
])
expect
(
subject
.
occurrences
).
to
eq
([
critical_high
,
critical_medium
,
high_high
,
unknown_high
,
unknown_medium
,
unknown_low
])
end
end
end
end
end
end
end
context
'by report type'
do
before
do
context
'when sast'
do
stub_licensed_features
(
sast:
true
,
dependency_scanning:
true
,
container_scanning:
true
,
dast:
true
)
let
(
:params
)
{
{
report_type:
%w[sast]
}
}
# Stub out deduplication, if not done the expectations will vary based on the fixtures (which may/may not have duplicates)
let
(
:sast_report_fingerprints
)
{
pipeline
.
security_reports
.
reports
[
'sast'
].
occurrences
.
map
(
&
:location
).
map
(
&
:fingerprint
)
}
disable_deduplication
end
it
'includes only sast'
do
subject
{
described_class
.
new
(
pipeline:
pipeline
,
params:
params
).
execute
}
expect
(
subject
.
occurrences
.
map
(
&
:location_fingerprint
)).
to
match_array
(
sast_report_fingerprints
)
expect
(
subject
.
occurrences
.
count
).
to
eq
(
sast_count
)
end
end
context
'when dependency_scanning'
do
context
'occurrences'
do
let
(
:params
)
{
{
report_type:
%w[dependency_scanning]
}
}
it
'assigns commit sha to findings'
do
let
(
:ds_report_fingerprints
)
{
pipeline
.
security_reports
.
reports
[
'dependency_scanning'
].
occurrences
.
map
(
&
:location
).
map
(
&
:fingerprint
)
}
expect
(
subject
.
occurrences
.
map
(
&
:sha
).
uniq
).
to
eq
([
pipeline
.
sha
])
end
it
'includes only dependency_scanning'
do
context
'by order'
do
expect
(
subject
.
occurrences
.
map
(
&
:location_fingerprint
)).
to
match_array
(
ds_report_fingerprints
)
let
(
:params
)
{
{
report_type:
%w[sast]
}
}
expect
(
subject
.
occurrences
.
count
).
to
eq
(
ds_count
)
let!
(
:high_high
)
{
build
(
:vulnerabilities_occurrence
,
confidence: :high
,
severity: :high
)
}
let!
(
:critical_medium
)
{
build
(
:vulnerabilities_occurrence
,
confidence: :medium
,
severity: :critical
)
}
let!
(
:critical_high
)
{
build
(
:vulnerabilities_occurrence
,
confidence: :high
,
severity: :critical
)
}
let!
(
:unknown_high
)
{
build
(
:vulnerabilities_occurrence
,
confidence: :high
,
severity: :unknown
)
}
let!
(
:unknown_medium
)
{
build
(
:vulnerabilities_occurrence
,
confidence: :medium
,
severity: :unknown
)
}
let!
(
:unknown_low
)
{
build
(
:vulnerabilities_occurrence
,
confidence: :low
,
severity: :unknown
)
}
it
'orders by severity and confidence'
do
allow_next_instance_of
(
described_class
)
do
|
pipeline_vulnerabilities_finder
|
allow
(
pipeline_vulnerabilities_finder
).
to
receive
(
:filter
).
and_return
([
unknown_low
,
unknown_medium
,
critical_high
,
unknown_high
,
critical_medium
,
high_high
])
expect
(
subject
.
occurrences
).
to
eq
([
critical_high
,
critical_medium
,
high_high
,
unknown_high
,
unknown_medium
,
unknown_low
])
end
end
end
end
end
end
context
'when dast'
do
context
'by report type'
do
let
(
:params
)
{
{
report_type:
%w[dast]
}
}
context
'when sast'
do
let
(
:dast_report_fingerprints
)
{
pipeline
.
security_reports
.
reports
[
'dast'
].
occurrences
.
map
(
&
:location
).
map
(
&
:fingerprint
)
}
let
(
:params
)
{
{
report_type:
%w[sast]
}
}
let
(
:sast_report_fingerprints
)
{
pipeline
.
security_reports
.
reports
[
'sast'
].
occurrences
.
map
(
&
:location
).
map
(
&
:fingerprint
)
}
it
'includes only dast'
do
it
'includes only sast'
do
expect
(
subject
.
occurrences
.
map
(
&
:location_fingerprint
)).
to
match_array
(
dast_report_fingerprints
)
expect
(
subject
.
occurrences
.
map
(
&
:location_fingerprint
)).
to
match_array
(
sast_report_fingerprints
)
expect
(
subject
.
occurrences
.
count
).
to
eq
(
dast_count
)
expect
(
subject
.
occurrences
.
count
).
to
eq
(
sast_count
)
end
end
end
end
context
'when container_scanning'
do
context
'when dependency_scanning'
do
let
(
:params
)
{
{
report_type:
%w[container_scanning]
}
}
let
(
:params
)
{
{
report_type:
%w[dependency_scanning]
}
}
let
(
:ds_report_fingerprints
)
{
pipeline
.
security_reports
.
reports
[
'dependency_scanning'
].
occurrences
.
map
(
&
:location
).
map
(
&
:fingerprint
)
}
it
'includes only container_scanning'
do
it
'includes only dependency_scanning'
do
fingerprints
=
pipeline
.
security_reports
.
reports
[
'container_scanning'
].
occurrences
.
map
(
&
:location
).
map
(
&
:fingerprint
)
expect
(
subject
.
occurrences
.
map
(
&
:location_fingerprint
)).
to
match_array
(
ds_report_fingerprints
)
expect
(
subject
.
occurrences
.
map
(
&
:location_fingerprint
)).
to
match_array
(
fingerprints
)
expect
(
subject
.
occurrences
.
count
).
to
eq
(
ds_count
)
expect
(
subject
.
occurrences
.
count
).
to
eq
(
cs_count
)
end
end
end
end
end
context
'by scope'
do
context
'when dast'
do
let
(
:ds_occurrence
)
{
pipeline
.
security_reports
.
reports
[
"dependency_scanning"
].
occurrences
.
first
}
let
(
:params
)
{
{
report_type:
%w[dast]
}
}
let
(
:sast_occurrence
)
{
pipeline
.
security_reports
.
reports
[
"sast"
].
occurrences
.
first
}
let
(
:dast_report_fingerprints
)
{
pipeline
.
security_reports
.
reports
[
'dast'
].
occurrences
.
map
(
&
:location
).
map
(
&
:fingerprint
)
}
let!
(
:feedback
)
do
[
create
(
:vulnerability_feedback
,
:dismissal
,
:dependency_scanning
,
project:
project
,
pipeline:
pipeline
,
project_fingerprint:
ds_occurrence
.
project_fingerprint
,
vulnerability_data:
ds_occurrence
.
raw_metadata
),
create
(
:vulnerability_feedback
,
:dismissal
,
:sast
,
project:
project
,
pipeline:
pipeline
,
project_fingerprint:
sast_occurrence
.
project_fingerprint
,
vulnerability_data:
sast_occurrence
.
raw_metadata
)
]
end
context
'when unscoped'
do
it
'includes only dast'
do
subject
{
described_class
.
new
(
pipeline:
pipeline
).
execute
}
expect
(
subject
.
occurrences
.
map
(
&
:location_fingerprint
)).
to
match_array
(
dast_report_fingerprints
)
expect
(
subject
.
occurrences
.
count
).
to
eq
(
dast_count
)
it
'returns non-dismissed vulnerabilities'
do
expect
(
subject
.
occurrences
.
count
).
to
eq
(
cs_count
+
dast_count
+
ds_count
+
sast_count
-
feedback
.
count
)
expect
(
subject
.
occurrences
.
map
(
&
:project_fingerprint
)).
not_to
include
(
*
feedback
.
map
(
&
:project_fingerprint
))
end
end
end
end
context
'when `dismissed`
'
do
context
'when container_scanning
'
do
subject
{
described_class
.
new
(
pipeline:
pipeline
,
params:
{
report_type:
%w[dependency_scanning]
,
scope:
'dismissed'
}
).
execute
}
let
(
:params
)
{
{
report_type:
%w[container_scanning]
}
}
it
'returns non-dismissed vulnerabilities
'
do
it
'includes only container_scanning
'
do
expect
(
subject
.
occurrences
.
count
).
to
eq
(
ds_count
-
1
)
fingerprints
=
pipeline
.
security_reports
.
reports
[
'container_scanning'
].
occurrences
.
map
(
&
:location
).
map
(
&
:fingerprint
)
expect
(
subject
.
occurrences
.
map
(
&
:project_fingerprint
)).
not_to
include
(
ds_occurrence
.
project_fingerprint
)
expect
(
subject
.
occurrences
.
map
(
&
:location_fingerprint
)).
to
match_array
(
fingerprints
)
e
nd
e
xpect
(
subject
.
occurrences
.
count
).
to
eq
(
cs_count
)
end
end
end
end
context
'when `all`'
do
context
'by scope'
do
let
(
:params
)
{
{
report_type:
%w[sast dast container_scanning dependency_scanning]
,
scope:
'all'
}
}
let
(
:ds_occurrence
)
{
pipeline
.
security_reports
.
reports
[
"dependency_scanning"
].
occurrences
.
first
}
let
(
:sast_occurrence
)
{
pipeline
.
security_reports
.
reports
[
"sast"
].
occurrences
.
first
}
let!
(
:feedback
)
do
[
create
(
:vulnerability_feedback
,
:dismissal
,
:dependency_scanning
,
project:
project
,
pipeline:
pipeline
,
project_fingerprint:
ds_occurrence
.
project_fingerprint
,
vulnerability_data:
ds_occurrence
.
raw_metadata
),
create
(
:vulnerability_feedback
,
:dismissal
,
:sast
,
project:
project
,
pipeline:
pipeline
,
project_fingerprint:
sast_occurrence
.
project_fingerprint
,
vulnerability_data:
sast_occurrence
.
raw_metadata
)
]
end
it
'returns all vulnerabilities'
do
context
'when unscoped'
do
expect
(
subject
.
occurrences
.
count
).
to
eq
(
cs_count
+
dast_count
+
ds_count
+
sast_count
)
subject
{
described_class
.
new
(
pipeline:
pipeline
).
execute
}
end
it
'returns non-dismissed vulnerabilities'
do
expect
(
subject
.
occurrences
.
count
).
to
eq
(
cs_count
+
dast_count
+
ds_count
+
sast_count
-
feedback
.
count
)
expect
(
subject
.
occurrences
.
map
(
&
:project_fingerprint
)).
not_to
include
(
*
feedback
.
map
(
&
:project_fingerprint
))
end
end
end
end
context
'by severity'
do
context
'when `dismissed`'
do
context
'when unscoped'
do
subject
{
described_class
.
new
(
pipeline:
pipeline
,
params:
{
report_type:
%w[dependency_scanning]
,
scope:
'dismissed'
}
).
execute
}
subject
{
described_class
.
new
(
pipeline:
pipeline
).
execute
}
it
'returns all vulnerability severity level
s'
do
it
'returns non-dismissed vulnerabilitie
s'
do
expect
(
subject
.
occurrences
.
map
(
&
:severity
).
uniq
).
to
match_array
(
%w[unknown low medium high critical info]
)
expect
(
subject
.
occurrences
.
count
).
to
eq
(
ds_count
-
1
)
e
nd
e
xpect
(
subject
.
occurrences
.
map
(
&
:project_fingerprint
)).
not_to
include
(
ds_occurrence
.
project_fingerprint
)
end
end
end
context
'when `low
`'
do
context
'when `all
`'
do
subject
{
described_class
.
new
(
pipeline:
pipeline
,
params:
{
severity:
'low'
}
).
execute
}
let
(
:params
)
{
{
report_type:
%w[sast dast container_scanning dependency_scanning]
,
scope:
'all'
}
}
it
'returns only low-severity vulnerabilities'
do
it
'returns all vulnerabilities'
do
expect
(
subject
.
occurrences
.
map
(
&
:severity
).
uniq
).
to
match_array
(
%w[low]
)
expect
(
subject
.
occurrences
.
count
).
to
eq
(
cs_count
+
dast_count
+
ds_count
+
sast_count
)
end
end
end
end
end
end
context
'by confidence
'
do
context
'by severity
'
do
context
'when unscoped'
do
context
'when unscoped'
do
subject
{
described_class
.
new
(
pipeline:
pipeline
).
execute
}
subject
{
described_class
.
new
(
pipeline:
pipeline
).
execute
}
it
'returns all vulnerability confidence levels'
do
it
'returns all vulnerability severity levels'
do
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]
)
end
end
end
end
context
'when `medium
`'
do
context
'when `low
`'
do
subject
{
described_class
.
new
(
pipeline:
pipeline
,
params:
{
confidence:
'medium
'
}
).
execute
}
subject
{
described_class
.
new
(
pipeline:
pipeline
,
params:
{
severity:
'low
'
}
).
execute
}
it
'returns only medium-confidence vulnerabilities'
do
it
'returns only low-severity vulnerabilities'
do
expect
(
subject
.
occurrences
.
map
(
&
:confidence
).
uniq
).
to
match_array
(
%w[medium]
)
expect
(
subject
.
occurrences
.
map
(
&
:severity
).
uniq
).
to
match_array
(
%w[low]
)
end
end
end
end
end
end
context
'by all filters
'
do
context
'by confidence
'
do
context
'with found entity
'
do
context
'when unscoped
'
do
let
(
:params
)
{
{
report_type:
%w[sast dast container_scanning dependency_scanning]
,
scope:
'all'
}
}
subject
{
described_class
.
new
(
pipeline:
pipeline
).
execute
}
it
'filters by all params'
do
it
'returns all vulnerability confidence levels'
do
expect
(
subject
.
occurrences
.
count
).
to
eq
(
cs_count
+
dast_count
+
ds_count
+
sast_count
)
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]
)
end
end
end
end
context
'without found entity
'
do
context
'when `medium`
'
do
let
(
:params
)
{
{
report_type:
%w[code_quality]
}
}
subject
{
described_class
.
new
(
pipeline:
pipeline
,
params:
{
confidence:
'medium'
}
).
execute
}
it
'did not find anything'
do
it
'returns only medium-confidence vulnerabilities'
do
expect
(
subject
.
created_at
).
to
be_nil
expect
(
subject
.
occurrences
.
map
(
&
:confidence
).
uniq
).
to
match_array
(
%w[medium]
)
expect
(
subject
.
occurrences
).
to
be_empty
end
end
end
end
end
end
context
'without params'
do
context
'by all filters'
do
subject
{
described_class
.
new
(
pipeline:
pipeline
).
execute
}
context
'with found entity'
do
let
(
:params
)
{
{
report_type:
%w[sast dast container_scanning dependency_scanning]
,
scope:
'all'
}
}
it
'
returns all report_type
s'
do
it
'
filters by all param
s'
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
(
&
: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]
)
end
end
end
end
context
'when matching vulnerability records exist'
do
context
'without found entity'
do
before
do
let
(
:params
)
{
{
report_type:
%w[code_quality]
}
}
create
(
:vulnerabilities_finding
,
:confirmed
,
project:
project
,
report_type:
'sast'
,
project_fingerprint:
confirmed_fingerprint
)
create
(
:vulnerabilities_finding
,
:resolved
,
project:
project
,
report_type:
'sast'
,
project_fingerprint:
resolved_fingerprint
)
create
(
:vulnerabilities_finding
,
:dismissed
,
project:
project
,
report_type:
'sast'
,
project_fingerprint:
dismissed_fingerprint
)
end
let
(
:confirmed_fingerprint
)
do
it
'did not find anything'
do
Digest
::
SHA1
.
hexdigest
(
expect
(
subject
.
created_at
).
to
be_nil
'python/hardcoded/hardcoded-tmp.py:52865813c884a507be1f152d654245af34aba8a391626d01f1ab6d3f52ec8779:B108'
)
expect
(
subject
.
occurrences
).
to
be_empty
end
let
(
:resolved_fingerprint
)
do
Digest
::
SHA1
.
hexdigest
(
'groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:47:PREDICTABLE_RANDOM'
)
end
end
end
end
let
(
:dismissed_fingerprint
)
do
context
'without params'
do
Digest
::
SHA1
.
hexdigest
(
subject
{
described_class
.
new
(
pipeline:
pipeline
).
execute
}
'groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:41:PREDICTABLE_RANDOM'
)
end
subject
{
described_class
.
new
(
pipeline:
pipeline
,
params:
{
report_type:
%w[sast]
,
scope:
'all'
}).
execute
}
it
'returns all report_types'
do
expect
(
subject
.
occurrences
.
count
).
to
eq
(
cs_count
+
dast_count
+
ds_count
+
sast_count
)
end
end
it
'assigns vulnerability records to findings providing them with computed state'
do
context
'when matching vulnerability records exist'
do
confirmed
=
subject
.
occurrences
.
find
{
|
f
|
f
.
project_fingerprint
==
confirmed_fingerprint
}
before
do
resolved
=
subject
.
occurrences
.
find
{
|
f
|
f
.
project_fingerprint
==
resolved_fingerprint
}
create
(
:vulnerabilities_finding
,
dismissed
=
subject
.
occurrences
.
find
{
|
f
|
f
.
project_fingerprint
==
dismissed_fingerprint
}
:confirmed
,
project:
project
,
report_type:
'sast'
,
project_fingerprint:
confirmed_fingerprint
)
create
(
:vulnerabilities_finding
,
:resolved
,
project:
project
,
report_type:
'sast'
,
project_fingerprint:
resolved_fingerprint
)
create
(
:vulnerabilities_finding
,
:dismissed
,
project:
project
,
report_type:
'sast'
,
project_fingerprint:
dismissed_fingerprint
)
end
expect
(
confirmed
.
state
).
to
eq
'confirmed'
let
(
:confirmed_fingerprint
)
do
expect
(
resolved
.
state
).
to
eq
'resolved'
Digest
::
SHA1
.
hexdigest
(
expect
(
dismissed
.
state
).
to
eq
'dismissed'
'python/hardcoded/hardcoded-tmp.py:52865813c884a507be1f152d654245af34aba8a391626d01f1ab6d3f52ec8779:B108'
)
expect
(
subject
.
occurrences
-
[
confirmed
,
resolved
,
dismissed
]).
to
all
(
have_attributes
(
state:
'detected'
))
end
end
end
context
'when being tested for sort stability'
do
let
(
:resolved_fingerprint
)
do
let
(
:params
)
{
{
report_type:
%w[sast]
}
}
Digest
::
SHA1
.
hexdigest
(
'groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:47:PREDICTABLE_RANDOM'
)
end
it
'maintains the order of the occurrences having the same severity and confidence'
do
let
(
:dismissed_fingerprint
)
do
select_proc
=
proc
{
|
o
|
o
.
severity
==
'medium'
&&
o
.
confidence
==
'high'
}
Digest
::
SHA1
.
hexdigest
(
report_occurrences
=
pipeline
.
security_reports
.
reports
[
'sast'
].
occurrences
.
select
(
&
select_proc
)
'groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:41:PREDICTABLE_RANDOM'
)
end
found_occurrences
=
subject
.
occurrences
.
select
(
&
select_proc
)
subject
{
described_class
.
new
(
pipeline:
pipeline
,
params:
{
report_type:
%w[sast]
,
scope:
'all'
}).
execute
}
found_occurrences
.
each_with_index
do
|
found
,
i
|
it
'assigns vulnerability records to findings providing them with computed state'
do
expect
(
found
.
metadata
[
'cve'
]).
to
eq
(
report_occurrences
[
i
].
compare_key
)
confirmed
=
subject
.
occurrences
.
find
{
|
f
|
f
.
project_fingerprint
==
confirmed_fingerprint
}
end
resolved
=
subject
.
occurrences
.
find
{
|
f
|
f
.
project_fingerprint
==
resolved_fingerprint
}
end
dismissed
=
subject
.
occurrences
.
find
{
|
f
|
f
.
project_fingerprint
==
dismissed_fingerprint
}
end
def
read_fixture
(
fixture
)
expect
(
confirmed
.
state
).
to
eq
'confirmed'
Gitlab
::
Json
.
parse
(
File
.
read
(
fixture
.
file
.
path
))
expect
(
resolved
.
state
).
to
eq
'resolved'
expect
(
dismissed
.
state
).
to
eq
'dismissed'
expect
(
subject
.
occurrences
-
[
confirmed
,
resolved
,
dismissed
]).
to
all
(
have_attributes
(
state:
'detected'
))
end
end
end
end
end
context
'container_scanning'
do
context
'when being tested for sort stability'
do
let_it_be
(
:artifact_cs
)
{
create
(
:ee_ci_job_artifact
,
:container_scanning
,
job:
build_cs
,
project:
project
)
}
let
(
:params
)
{
{
report_type:
%w[sast]
}
}
let
(
:cs_count
)
{
read_fixture
(
artifact_cs
)[
'vulnerabilities'
].
count
}
it_behaves_like
'a pipeline vulnerabilities finder'
it
'maintains the order of the occurrences having the same severity and confidence'
do
end
select_proc
=
proc
{
|
o
|
o
.
severity
==
'medium'
&&
o
.
confidence
==
'high'
}
report_occurrences
=
pipeline
.
security_reports
.
reports
[
'sast'
].
occurrences
.
select
(
&
select_proc
)
context
'deprecated container_scanning'
do
found_occurrences
=
subject
.
occurrences
.
select
(
&
select_proc
)
let_it_be
(
:artifact_cs
)
{
create
(
:ee_ci_job_artifact
,
:deprecated_container_scanning_report
,
job:
build_cs
,
project:
project
)
}
let
(
:cs_count
)
{
read_fixture
(
artifact_cs
)[
'unapproved'
].
count
}
it_behaves_like
'a pipeline vulnerabilities finder'
found_occurrences
.
each_with_index
do
|
found
,
i
|
expect
(
found
.
metadata
[
'cve'
]).
to
eq
(
report_occurrences
[
i
].
compare_key
)
end
end
end
def
read_fixture
(
fixture
)
Gitlab
::
Json
.
parse
(
File
.
read
(
fixture
.
file
.
path
))
end
end
end
end
end
ee/spec/fixtures/security_reports/feature-branch/gl-container-scanning-report.json
View file @
19ae43b3
{
{
"image"
:
"registry.gitlab.com/bikebilly/auto-devops-10-6/feature-branch:e7315ba964febb11bac8f5cd6ec433db8a3a1583"
,
"version"
:
"2.4"
,
"unapproved"
:
[
"CVE-2017-15650"
],
"vulnerabilities"
:
[
"vulnerabilities"
:
[
{
{
"featurename"
:
"musl"
,
"id"
:
"e987fa54ff94e1d0e716814861459d2eb10bd27a0ba8ca243428669d8885ce68"
,
"featureversion"
:
"1.1.14-r15"
,
"category"
:
"container_scanning"
,
"vulnerability"
:
"CVE-2017-15650"
,
"message"
:
"CVE-2017-15650 in musl"
,
"namespace"
:
"alpine:v3.4"
,
"description"
:
"musl:1.1.18-r3 is affected by CVE-2017-15650"
,
"description"
:
""
,
"cve"
:
"alpine:v3.7:musl:CVE-2017-15650"
,
"link"
:
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-15650"
,
"severity"
:
"High"
,
"severity"
:
"Medium"
,
"confidence"
:
"Unknown"
,
"fixedby"
:
"1.1.14-r16"
"solution"
:
"Upgrade musl from 1.1.18-r3 to 1.1.18-r4"
,
"scanner"
:
{
"id"
:
"klar"
,
"name"
:
"klar"
},
"location"
:
{
"dependency"
:
{
"package"
:
{
"name"
:
"musl"
},
"version"
:
"1.1.18-r3"
},
"operating_system"
:
"alpine:v3.7"
,
"image"
:
"registry.gitlab.com/bikebilly/auto-devops-10-6/feature-branch:e7315ba964febb11bac8f5cd6ec433db8a3a1583"
},
"identifiers"
:
[
{
"type"
:
"cve"
,
"name"
:
"CVE-2017-15650"
,
"value"
:
"CVE-2017-15650"
,
"url"
:
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-15650"
}
],
"links"
:
[
{
"url"
:
"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-15650"
}
]
}
}
]
],
"remediations"
:
[]
}
}
ee/spec/lib/gitlab/ci/parsers/security/container_scanning_spec.rb
View file @
19ae43b3
...
@@ -15,41 +15,33 @@ describe Gitlab::Ci::Parsers::Security::ContainerScanning do
...
@@ -15,41 +15,33 @@ describe Gitlab::Ci::Parsers::Security::ContainerScanning do
end
end
describe
'#parse!'
do
describe
'#parse!'
do
using
RSpec
::
Parameterized
::
TableSyntax
let
(
:artifact
)
{
create
(
:ee_ci_job_artifact
,
:container_scanning
)
}
let
(
:image
)
{
'registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256:bc09fe2e0721dfaeee79364115aeedf2174cce0947b9ae5fe7c33312ee019a4e'
}
where
(
:report_type
,
:image
,
:version
)
do
it
"parses all identifiers and occurrences for unapproved vulnerabilities"
do
:deprecated_container_scanning_report
|
'registry.gitlab.com/groulot/container-scanning-test/master:5f21de6956aee99ddb68ae49498662d9872f50ff'
|
'1.3'
expect
(
report
.
occurrences
.
length
).
to
eq
(
8
)
:container_scanning
|
'registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256:bc09fe2e0721dfaeee79364115aeedf2174cce0947b9ae5fe7c33312ee019a4e'
|
'2.3'
expect
(
report
.
identifiers
.
length
).
to
eq
(
8
)
expect
(
report
.
scanners
.
length
).
to
eq
(
1
)
end
end
with_them
do
it
'generates expected location'
do
let
(
:artifact
)
{
create
(
:ee_ci_job_artifact
,
report_type
)
}
location
=
report
.
occurrences
.
first
.
location
it
"parses all identifiers and occurrences for unapproved vulnerabilities"
do
expect
(
location
).
to
be_a
(
::
Gitlab
::
Ci
::
Reports
::
Security
::
Locations
::
ContainerScanning
)
expect
(
report
.
occurrences
.
length
).
to
eq
(
8
)
expect
(
location
).
to
have_attributes
(
expect
(
report
.
identifiers
.
length
).
to
eq
(
8
)
image:
image
,
expect
(
report
.
scanners
.
length
).
to
eq
(
1
)
operating_system:
'debian:9'
,
end
package_name:
'glibc'
,
package_version:
'2.24-11+deb9u3'
it
'generates expected location'
do
)
location
=
report
.
occurrences
.
first
.
location
end
expect
(
location
).
to
be_a
(
::
Gitlab
::
Ci
::
Reports
::
Security
::
Locations
::
ContainerScanning
)
it
"generates expected metadata_version"
do
expect
(
location
).
to
have_attributes
(
expect
(
report
.
occurrences
.
first
.
metadata_version
).
to
eq
(
'2.3'
)
image:
image
,
end
operating_system:
'debian:9'
,
package_name:
'glibc'
,
it
"adds report image's name to raw_metadata"
do
package_version:
'2.24-11+deb9u3'
expect
(
Gitlab
::
Json
.
parse
(
report
.
occurrences
.
first
.
raw_metadata
).
dig
(
'location'
,
'image'
)).
to
eq
(
image
)
)
end
it
"generates expected metadata_version"
do
expect
(
report
.
occurrences
.
first
.
metadata_version
).
to
eq
(
version
)
end
it
"adds report image's name to raw_metadata"
do
expect
(
Gitlab
::
Json
.
parse
(
report
.
occurrences
.
first
.
raw_metadata
).
dig
(
'location'
,
'image'
)).
to
eq
(
image
)
end
end
end
end
end
end
end
ee/spec/lib/gitlab/ci/parsers/security/formatters/deprecated_container_scanning_spec.rb
deleted
100644 → 0
View file @
a91546fe
# frozen_string_literal: true
require
'spec_helper'
describe
Gitlab
::
Ci
::
Parsers
::
Security
::
Formatters
::
DeprecatedContainerScanning
do
let
(
:vulnerability
)
{
raw_report
[
'vulnerabilities'
].
first
}
describe
'#format'
do
let
(
:raw_report
)
do
Gitlab
::
Json
.
parse!
(
File
.
read
(
Rails
.
root
.
join
(
'ee/spec/fixtures/security_reports/deprecated/gl-container-scanning-report.json'
)
)
)
end
it
'formats the vulnerability into the 1.3 format'
do
formatter
=
described_class
.
new
(
'image_name'
)
expect
(
formatter
.
format
(
vulnerability
)).
to
eq
(
{
'category'
=>
'container_scanning'
,
'message'
=>
'CVE-2017-18269 in glibc'
,
'confidence'
=>
'Unknown'
,
'cve'
=>
'CVE-2017-18269'
,
'identifiers'
=>
[
{
'type'
=>
'cve'
,
'name'
=>
'CVE-2017-18269'
,
'value'
=>
'CVE-2017-18269'
,
'url'
=>
'https://security-tracker.debian.org/tracker/CVE-2017-18269'
}
],
'location'
=>
{
'image'
=>
'image_name'
,
'operating_system'
=>
'debian:9'
,
'dependency'
=>
{
'package'
=>
{
'name'
=>
'glibc'
},
'version'
=>
'2.24-11+deb9u3'
}
},
'links'
=>
[{
'url'
=>
'https://security-tracker.debian.org/tracker/CVE-2017-18269'
}],
'description'
=>
'SSE2-optimized memmove implementation problem.'
,
'scanner'
=>
{
'id'
=>
'clair'
,
'name'
=>
'Clair'
},
'severity'
=>
'critical'
,
'solution'
=>
'Upgrade glibc from 2.24-11+deb9u3 to 2.24-11+deb9u4'
}
)
end
end
end
ee/spec/lib/gitlab/ci/parsers/security/formatters/deprecated_formatted_container_scanning_vulnerability_spec.rb
deleted
100644 → 0
View file @
a91546fe
# frozen_string_literal: true
require
'spec_helper'
describe
Gitlab
::
Ci
::
Parsers
::
Security
::
Formatters
::
DeprecatedFormattedContainerScanningVulnerability
do
let
(
:raw_report
)
do
Gitlab
::
Json
.
parse!
(
File
.
read
(
Rails
.
root
.
join
(
'ee/spec/fixtures/security_reports/deprecated/gl-container-scanning-report.json'
)
)
)
end
let
(
:vulnerability
)
{
raw_report
[
'vulnerabilities'
].
first
}
let
(
:data_with_all_keys
)
do
raw_report
[
'vulnerabilities'
].
first
.
merge
(
'description'
=>
'Better hurry and fix that.'
,
'featurename'
=>
'hexes'
,
'featureversion'
=>
'6.6.6'
,
'fixedby'
=>
'6.6.7'
,
'link'
=>
'https://theintercept.com'
,
'namespace'
=>
'malevolences'
,
'vulnerability'
=>
'Level 9000 Soul Breach'
)
end
subject
{
described_class
.
new
(
data_with_all_keys
)
}
describe
'#message'
do
it
'creates a message from the vulnerability and featurename'
do
expect
(
subject
.
message
).
to
eq
(
'Level 9000 Soul Breach in hexes'
)
end
context
'when there is no featurename'
do
it
'uses vulnerability for the message'
do
data_without_featurename
=
data_with_all_keys
.
deep_dup
.
merge
(
'featurename'
=>
''
)
formatted_vulnerability
=
described_class
.
new
(
data_without_featurename
)
expect
(
formatted_vulnerability
.
message
).
to
eq
(
'Level 9000 Soul Breach'
)
end
end
end
describe
'#description'
do
it
'uses the given description'
do
expect
(
subject
.
description
).
to
eq
(
'Better hurry and fix that.'
)
end
context
'when there is no description'
do
let
(
:data_without_description
)
{
data_with_all_keys
.
deep_dup
.
merge
(
'description'
=>
''
)
}
it
'creates a description from the featurename and featureversion'
do
formatted_vulnerability
=
described_class
.
new
(
data_without_description
)
expect
(
formatted_vulnerability
.
description
).
to
eq
(
'hexes:6.6.6 is affected by Level 9000 Soul Breach'
)
end
context
'when there is no featureversion'
do
it
'creates a description from the featurename'
do
data_without_featureversion
=
data_without_description
.
deep_dup
.
merge
(
'featureversion'
=>
''
)
formatted_vulnerability
=
described_class
.
new
(
data_without_featureversion
)
expect
(
formatted_vulnerability
.
description
).
to
eq
(
'hexes is affected by Level 9000 Soul Breach'
)
end
end
context
'when there is no featurename and no featureversion'
do
it
'creates a description from the namespace'
do
data_only_namespace
=
data_without_description
.
deep_dup
.
merge
(
'featurename'
=>
''
,
'featureversion'
=>
''
)
formatted_vulnerability
=
described_class
.
new
(
data_only_namespace
)
expect
(
formatted_vulnerability
.
description
).
to
eq
(
'malevolences is affected by Level 9000 Soul Breach'
)
end
end
end
end
describe
'#severity'
do
using
RSpec
::
Parameterized
::
TableSyntax
where
(
:report_severity_category
,
:gitlab_severity_category
)
do
'Unknown'
|
'unknown'
'Negligible'
|
'low'
'Low'
|
'low'
'Medium'
|
'medium'
'High'
|
'high'
'Critical'
|
'critical'
'Defcon1'
|
'critical'
end
with_them
do
it
'translates the severity into our categorization'
do
data_with_severity
=
data_with_all_keys
.
deep_dup
.
merge
(
'severity'
=>
report_severity_category
)
formatted_vulnerability
=
described_class
.
new
(
data_with_severity
)
expect
(
formatted_vulnerability
.
severity
).
to
eq
(
gitlab_severity_category
)
end
end
context
'when the given severity is not valid'
do
it
'throws a parser error'
do
data_with_invalid_severity
=
vulnerability
.
deep_dup
.
merge
(
'severity'
=>
'cats, curses, and <coffee>'
)
formatted_vulnerability
=
described_class
.
new
(
data_with_invalid_severity
)
expect
{
formatted_vulnerability
.
severity
}.
to
raise_error
(
::
Gitlab
::
Ci
::
Parsers
::
Security
::
Common
::
SecurityReportParserError
,
'Unknown severity in container scanning report: cats, curses, and <coffee>'
)
end
end
end
describe
'#solution'
do
it
'creates a solution from the featurename, featureversion, and fixedby'
do
expect
(
subject
.
solution
).
to
eq
(
'Upgrade hexes from 6.6.6 to 6.6.7'
)
end
context
'when there is no featurename'
do
it
'formats the solution using fixedby'
do
data_without_featurename
=
data_with_all_keys
.
deep_dup
.
merge
(
'featurename'
=>
''
)
formatted_vulnerability
=
described_class
.
new
(
data_without_featurename
)
expect
(
formatted_vulnerability
.
solution
).
to
eq
(
'Upgrade to 6.6.7'
)
end
end
context
'when there is no featureversion'
do
it
'formats a solution using featurename'
do
data_without_featureversion
=
data_with_all_keys
.
deep_dup
.
merge
(
'featureversion'
=>
''
)
formatted_vulnerability
=
described_class
.
new
(
data_without_featureversion
)
expect
(
formatted_vulnerability
.
solution
).
to
eq
(
'Upgrade hexes to 6.6.7'
)
end
end
context
'when there is no fixedby'
do
it
'does not include a solution'
do
data_without_fixedby
=
vulnerability
.
deep_dup
.
merge
(
'fixedby'
=>
''
)
formatted_vulnerability
=
described_class
.
new
(
data_without_fixedby
)
expect
(
formatted_vulnerability
.
solution
).
to
be_nil
end
end
end
describe
'#cve'
do
it
'reads the CVE from the vulnerability'
do
expect
(
subject
.
cve
).
to
eq
(
'Level 9000 Soul Breach'
)
end
end
describe
'#operating_system'
do
it
'reads the operating system from the namespace'
do
expect
(
subject
.
operating_system
).
to
eq
(
'malevolences'
)
end
end
describe
'#package_name'
do
it
'reads the package name from the featurename'
do
expect
(
subject
.
package_name
).
to
eq
(
'hexes'
)
end
end
describe
'#version'
do
it
'reads the version from featureversion'
do
expect
(
subject
.
version
).
to
eq
(
'6.6.6'
)
end
end
describe
'#url'
do
it
'reads the url from the link in the report'
do
expect
(
subject
.
url
).
to
eq
(
'https://theintercept.com'
)
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment