Commit 2dbab45a authored by Alan (Maciej) Paruszewski's avatar Alan (Maciej) Paruszewski Committed by charlie ablett

Add new security job artifact report cluster image scanning

parent a5c95756
...@@ -33,6 +33,7 @@ module Ci ...@@ -33,6 +33,7 @@ module Ci
secret_detection: 'gl-secret-detection-report.json', secret_detection: 'gl-secret-detection-report.json',
dependency_scanning: 'gl-dependency-scanning-report.json', dependency_scanning: 'gl-dependency-scanning-report.json',
container_scanning: 'gl-container-scanning-report.json', container_scanning: 'gl-container-scanning-report.json',
cluster_image_scanning: 'gl-cluster-image-scanning-report.json',
dast: 'gl-dast-report.json', dast: 'gl-dast-report.json',
license_scanning: 'gl-license-scanning-report.json', license_scanning: 'gl-license-scanning-report.json',
performance: 'performance.json', performance: 'performance.json',
...@@ -71,6 +72,7 @@ module Ci ...@@ -71,6 +72,7 @@ module Ci
secret_detection: :raw, secret_detection: :raw,
dependency_scanning: :raw, dependency_scanning: :raw,
container_scanning: :raw, container_scanning: :raw,
cluster_image_scanning: :raw,
dast: :raw, dast: :raw,
license_scanning: :raw, license_scanning: :raw,
...@@ -108,6 +110,7 @@ module Ci ...@@ -108,6 +110,7 @@ module Ci
sast sast
secret_detection secret_detection
requirements requirements
cluster_image_scanning
].freeze ].freeze
TYPE_AND_FORMAT_PAIRS = INTERNAL_TYPES.merge(REPORT_TYPES).freeze TYPE_AND_FORMAT_PAIRS = INTERNAL_TYPES.merge(REPORT_TYPES).freeze
...@@ -212,7 +215,8 @@ module Ci ...@@ -212,7 +215,8 @@ module Ci
coverage_fuzzing: 23, ## EE-specific coverage_fuzzing: 23, ## EE-specific
browser_performance: 24, ## EE-specific browser_performance: 24, ## EE-specific
load_performance: 25, ## EE-specific load_performance: 25, ## EE-specific
api_fuzzing: 26 ## EE-specific api_fuzzing: 26, ## EE-specific
cluster_image_scanning: 27 ## EE-specific
} }
# `file_location` indicates where actual files are stored. # `file_location` indicates where actual files are stored.
......
...@@ -14547,6 +14547,7 @@ Iteration ID wildcard values. ...@@ -14547,6 +14547,7 @@ Iteration ID wildcard values.
| <a id="jobartifactfiletypearchive"></a>`ARCHIVE` | ARCHIVE job artifact file type. | | <a id="jobartifactfiletypearchive"></a>`ARCHIVE` | ARCHIVE job artifact file type. |
| <a id="jobartifactfiletypebrowser_performance"></a>`BROWSER_PERFORMANCE` | BROWSER PERFORMANCE job artifact file type. | | <a id="jobartifactfiletypebrowser_performance"></a>`BROWSER_PERFORMANCE` | BROWSER PERFORMANCE job artifact file type. |
| <a id="jobartifactfiletypecluster_applications"></a>`CLUSTER_APPLICATIONS` | CLUSTER APPLICATIONS job artifact file type. | | <a id="jobartifactfiletypecluster_applications"></a>`CLUSTER_APPLICATIONS` | CLUSTER APPLICATIONS job artifact file type. |
| <a id="jobartifactfiletypecluster_image_scanning"></a>`CLUSTER_IMAGE_SCANNING` | CLUSTER IMAGE SCANNING job artifact file type. |
| <a id="jobartifactfiletypecobertura"></a>`COBERTURA` | COBERTURA job artifact file type. | | <a id="jobartifactfiletypecobertura"></a>`COBERTURA` | COBERTURA job artifact file type. |
| <a id="jobartifactfiletypecodequality"></a>`CODEQUALITY` | CODE QUALITY job artifact file type. | | <a id="jobartifactfiletypecodequality"></a>`CODEQUALITY` | CODE QUALITY job artifact file type. |
| <a id="jobartifactfiletypecontainer_scanning"></a>`CONTAINER_SCANNING` | CONTAINER SCANNING job artifact file type. | | <a id="jobartifactfiletypecontainer_scanning"></a>`CONTAINER_SCANNING` | CONTAINER SCANNING job artifact file type. |
......
...@@ -3064,6 +3064,18 @@ as artifacts. ...@@ -3064,6 +3064,18 @@ as artifacts.
The collected coverage fuzzing report uploads to GitLab as an artifact and is summarized in merge The collected coverage fuzzing report uploads to GitLab as an artifact and is summarized in merge
requests and the pipeline view. It's also used to provide data for security dashboards. requests and the pipeline view. It's also used to provide data for security dashboards.
##### `artifacts:reports:cluster_image_scanning` **(ULTIMATE)**
> - Introduced in GitLab 14.1.
> - Requires GitLab Runner 14.1 and above.
The `cluster_image_scanning` report collects `CLUSTER_IMAGE_SCANNING` vulnerabilities
as artifacts.
The collected `CLUSTER_IMAGE_SCANNING` report uploads to GitLab as an artifact and
is summarized in the pipeline view. It's also used to provide data for security
dashboards.
##### `artifacts:reports:dast` **(ULTIMATE)** ##### `artifacts:reports:dast` **(ULTIMATE)**
> - Introduced in GitLab 11.5. > - Introduced in GitLab 11.5.
......
...@@ -16,7 +16,7 @@ module Types ...@@ -16,7 +16,7 @@ module Types
def self.resolve_type(object, context) def self.resolve_type(object, context)
case object[:report_type] case object[:report_type]
when 'container_scanning' when 'container_scanning', 'cluster_image_scanning'
VulnerabilityLocation::ContainerScanningType VulnerabilityLocation::ContainerScanningType
when 'dependency_scanning' when 'dependency_scanning'
VulnerabilityLocation::DependencyScanningType VulnerabilityLocation::DependencyScanningType
......
...@@ -16,6 +16,7 @@ module EE ...@@ -16,6 +16,7 @@ module EE
secret_detection: :secret_detection, secret_detection: :secret_detection,
dependency_scanning: :dependency_scanning, dependency_scanning: :dependency_scanning,
container_scanning: :container_scanning, container_scanning: :container_scanning,
cluster_image_scanning: :cluster_image_scanning,
dast: :dast, dast: :dast,
coverage_fuzzing: :coverage_fuzzing, coverage_fuzzing: :coverage_fuzzing,
api_fuzzing: :api_fuzzing api_fuzzing: :api_fuzzing
......
...@@ -15,11 +15,12 @@ module EE ...@@ -15,11 +15,12 @@ module EE
# See https://gitlab.com/gitlab-org/gitlab/-/issues/297472 # See https://gitlab.com/gitlab-org/gitlab/-/issues/297472
after_destroy :log_geo_deleted_event after_destroy :log_geo_deleted_event
SECURITY_REPORT_FILE_TYPES = %w[sast secret_detection dependency_scanning container_scanning dast coverage_fuzzing api_fuzzing].freeze SECURITY_REPORT_FILE_TYPES = %w[sast secret_detection dependency_scanning container_scanning cluster_image_scanning dast coverage_fuzzing api_fuzzing].freeze
LICENSE_SCANNING_REPORT_FILE_TYPES = %w[license_scanning].freeze LICENSE_SCANNING_REPORT_FILE_TYPES = %w[license_scanning].freeze
DEPENDENCY_LIST_REPORT_FILE_TYPES = %w[dependency_scanning].freeze DEPENDENCY_LIST_REPORT_FILE_TYPES = %w[dependency_scanning].freeze
METRICS_REPORT_FILE_TYPES = %w[metrics].freeze METRICS_REPORT_FILE_TYPES = %w[metrics].freeze
CONTAINER_SCANNING_REPORT_TYPES = %w[container_scanning].freeze CONTAINER_SCANNING_REPORT_TYPES = %w[container_scanning].freeze
CLUSTER_IMAGE_SCANNING_REPORT_TYPES = %w[cluster_image_scanning].freeze
DAST_REPORT_TYPES = %w[dast].freeze DAST_REPORT_TYPES = %w[dast].freeze
REQUIREMENTS_REPORT_FILE_TYPES = %w[requirements].freeze REQUIREMENTS_REPORT_FILE_TYPES = %w[requirements].freeze
COVERAGE_FUZZING_REPORT_TYPES = %w[coverage_fuzzing].freeze COVERAGE_FUZZING_REPORT_TYPES = %w[coverage_fuzzing].freeze
...@@ -44,6 +45,10 @@ module EE ...@@ -44,6 +45,10 @@ module EE
with_file_types(CONTAINER_SCANNING_REPORT_TYPES) with_file_types(CONTAINER_SCANNING_REPORT_TYPES)
end end
scope :cluster_image_scanning_reports, -> do
with_file_types(CLUSTER_IMAGE_SCANNING_REPORT_TYPES)
end
scope :dast_reports, -> do scope :dast_reports, -> do
with_file_types(DAST_REPORT_TYPES) with_file_types(DAST_REPORT_TYPES)
end end
......
...@@ -46,6 +46,7 @@ module EE ...@@ -46,6 +46,7 @@ module EE
secret_detection: %i[secret_detection], secret_detection: %i[secret_detection],
dependency_scanning: %i[dependency_scanning], dependency_scanning: %i[dependency_scanning],
container_scanning: %i[container_scanning], container_scanning: %i[container_scanning],
cluster_image_scanning: %i[cluster_image_scanning],
dast: %i[dast], dast: %i[dast],
performance: %i[merge_request_performance_metrics], performance: %i[merge_request_performance_metrics],
browser_performance: %i[merge_request_performance_metrics], browser_performance: %i[merge_request_performance_metrics],
......
...@@ -332,6 +332,7 @@ module EE ...@@ -332,6 +332,7 @@ module EE
feature_available?(:secret_detection) || feature_available?(:secret_detection) ||
feature_available?(:dependency_scanning) || feature_available?(:dependency_scanning) ||
feature_available?(:container_scanning) || feature_available?(:container_scanning) ||
feature_available?(:cluster_image_scanning) ||
feature_available?(:dast) || feature_available?(:dast) ||
feature_available?(:coverage_fuzzing) || feature_available?(:coverage_fuzzing) ||
feature_available?(:api_fuzzing) feature_available?(:api_fuzzing)
......
...@@ -144,6 +144,7 @@ class License < ApplicationRecord ...@@ -144,6 +144,7 @@ class License < ApplicationRecord
api_fuzzing api_fuzzing
auto_rollback auto_rollback
cilium_alerts cilium_alerts
cluster_image_scanning
external_status_checks external_status_checks
container_scanning container_scanning
coverage_fuzzing coverage_fuzzing
......
...@@ -12,6 +12,7 @@ module EE ...@@ -12,6 +12,7 @@ module EE
license_scanning: ::Gitlab::Ci::Parsers::LicenseCompliance::LicenseScanning, license_scanning: ::Gitlab::Ci::Parsers::LicenseCompliance::LicenseScanning,
dependency_scanning: ::Gitlab::Ci::Parsers::Security::DependencyScanning, dependency_scanning: ::Gitlab::Ci::Parsers::Security::DependencyScanning,
container_scanning: ::Gitlab::Ci::Parsers::Security::ContainerScanning, container_scanning: ::Gitlab::Ci::Parsers::Security::ContainerScanning,
cluster_image_scanning: ::Gitlab::Ci::Parsers::Security::ContainerScanning,
dast: ::Gitlab::Ci::Parsers::Security::Dast, dast: ::Gitlab::Ci::Parsers::Security::Dast,
sast: ::Gitlab::Ci::Parsers::Security::Sast, sast: ::Gitlab::Ci::Parsers::Security::Sast,
api_fuzzing: ::Gitlab::Ci::Parsers::Security::Dast, api_fuzzing: ::Gitlab::Ci::Parsers::Security::Dast,
......
...@@ -25,7 +25,7 @@ module Gitlab ...@@ -25,7 +25,7 @@ module Gitlab
end end
def standard_vulnerability?(category) def standard_vulnerability?(category)
(valid_categories.keys - ['container_scanning']).include?(category) (valid_categories.keys - %w[container_scanning cluster_image_scanning]).include?(category)
end end
end end
end end
......
...@@ -6,7 +6,7 @@ FactoryBot.define do ...@@ -6,7 +6,7 @@ FactoryBot.define do
failure_reason { Ci::Build.failure_reasons[:protected_environment_failure] } failure_reason { Ci::Build.failure_reasons[:protected_environment_failure] }
end end
%i[api_fuzzing codequality container_scanning dast dependency_scanning license_scanning performance browser_performance load_performance sast secret_detection coverage_fuzzing].each do |report_type| %i[api_fuzzing codequality container_scanning cluster_image_scanning dast dependency_scanning license_scanning performance browser_performance load_performance sast secret_detection coverage_fuzzing].each do |report_type|
trait "legacy_#{report_type}".to_sym do trait "legacy_#{report_type}".to_sym do
success success
artifacts artifacts
...@@ -84,6 +84,18 @@ FactoryBot.define do ...@@ -84,6 +84,18 @@ FactoryBot.define do
end end
end end
trait :cluster_image_scanning_feature_branch do
after(:build) do |build|
build.job_artifacts << create(:ee_ci_job_artifact, :cluster_image_scanning_feature_branch, job: build)
end
end
trait :corrupted_cluster_image_scanning_report do
after(:build) do |build|
build.job_artifacts << create(:ee_ci_job_artifact, :corrupted_cluster_image_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)
......
...@@ -299,6 +299,16 @@ FactoryBot.define do ...@@ -299,6 +299,16 @@ FactoryBot.define do
end end
end end
trait :cluster_image_scanning do
file_format { :raw }
file_type { :cluster_image_scanning }
after(:build) do |artifact, _|
artifact.file = fixture_file_upload(
Rails.root.join('ee/spec/fixtures/security_reports/master/gl-cluster-image-scanning-report.json'), 'application/json')
end
end
trait :common_security_report do trait :common_security_report do
file_format { :raw } file_format { :raw }
file_type { :dependency_scanning } file_type { :dependency_scanning }
...@@ -339,6 +349,26 @@ FactoryBot.define do ...@@ -339,6 +349,26 @@ FactoryBot.define do
end end
end end
trait :cluster_image_scanning_feature_branch do
file_format { :raw }
file_type { :cluster_image_scanning }
after(:build) do |artifact, _|
artifact.file = fixture_file_upload(
Rails.root.join('ee/spec/fixtures/security_reports/feature-branch/gl-cluster-image-scanning-report.json'), 'application/json')
end
end
trait :corrupted_cluster_image_scanning_report do
file_format { :raw }
file_type { :cluster_image_scanning }
after(:build) do |artifact, _|
artifact.file = fixture_file_upload(
Rails.root.join('spec/fixtures/trace/sample_trace'), 'application/json')
end
end
trait :metrics do trait :metrics do
file_format { :gzip } file_format { :gzip }
file_type { :metrics } file_type { :metrics }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
FactoryBot.define do FactoryBot.define do
factory :ee_ci_pipeline, class: 'Ci::Pipeline', parent: :ci_pipeline do factory :ee_ci_pipeline, class: 'Ci::Pipeline', parent: :ci_pipeline do
%i[api_fuzzing browser_performance codequality container_scanning coverage_fuzzing dast dependency_list dependency_scanning license_scanning load_performance sast secret_detection].each do |report_type| %i[api_fuzzing browser_performance codequality container_scanning cluster_image_scanning coverage_fuzzing dast dependency_list dependency_scanning license_scanning load_performance sast secret_detection].each do |report_type|
trait "with_#{report_type}_report".to_sym do trait "with_#{report_type}_report".to_sym do
status { :success } status { :success }
...@@ -28,6 +28,22 @@ FactoryBot.define do ...@@ -28,6 +28,22 @@ FactoryBot.define do
end end
end end
trait :with_cluster_image_scanning_feature_branch do
status { :success }
after(:build) do |pipeline, evaluator|
pipeline.builds << build(:ee_ci_build, :cluster_image_scanning_feature_branch, pipeline: pipeline, project: pipeline.project)
end
end
trait :with_corrupted_cluster_image_scanning_report do
status { :success }
after(:build) do |pipeline, evaluator|
pipeline.builds << build(:ee_ci_build, :corrupted_cluster_image_scanning_report, pipeline: pipeline, project: pipeline.project)
end
end
trait :with_dependency_scanning_feature_branch do trait :with_dependency_scanning_feature_branch do
status { :success } status { :success }
......
...@@ -52,6 +52,10 @@ FactoryBot.define do ...@@ -52,6 +52,10 @@ FactoryBot.define do
category { 'container_scanning' } category { 'container_scanning' }
end end
trait :cluster_image_scanning do
category { 'cluster_image_scanning' }
end
trait :dast do trait :dast do
category { 'dast' } category { 'dast' }
end end
......
{
"version": "2.4",
"vulnerabilities": [
{
"id": "e987fa54ff94e1d0e716814861459d2eb10bd27a0ba8ca243428669d8885ce68",
"category": "cluster_image_scanning",
"message": "CVE-2017-15650 in musl",
"description": "musl:1.1.18-r3 is affected by CVE-2017-15650",
"cve": "alpine:v3.7:musl:CVE-2017-15650",
"severity": "High",
"confidence": "Unknown",
"solution": "Upgrade musl from 1.1.18-r3 to 1.1.18-r4",
"scanner": {
"id": "starboard",
"name": "Starboard"
},
"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": [],
"scan": {
"scanner": {
"id": "starboard",
"name": "Starboard",
"url": "https://github.com/aquasecurity/starboard",
"vendor": {
"name": "GitLab"
},
"version": "2.1.4"
},
"type": "cluster_image_scanning",
"status": "success"
}
}
{
"version": "2.3",
"vulnerabilities": [
{
"category": "cluster_image_scanning",
"message": "CVE-2017-18269 in glibc",
"description": "An SSE2-optimized memmove implementation for i386 in sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S in the GNU C Library (aka glibc or libc6) 2.21 through 2.27 does not correctly perform the overlapping memory check if the source memory range spans the middle of the address space, resulting in corrupt data being produced by the copy operation. This may disclose information to context-dependent attackers, or result in a denial of service, or, possibly, code execution.",
"cve": "debian:9:glibc:CVE-2017-18269",
"severity": "Critical",
"confidence": "Unknown",
"solution": "Upgrade glibc from 2.24-11+deb9u3 to 2.24-11+deb9u4",
"scanner": {
"id": "starboard",
"name": "Starboard"
},
"location": {
"dependency": {
"package": {
"name": "glibc"
},
"version": "2.24-11+deb9u3"
},
"operating_system": "debian:9",
"image": "registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256:bc09fe2e0721dfaeee79364115aeedf2174cce0947b9ae5fe7c33312ee019a4e"
},
"identifiers": [
{
"type": "cve",
"name": "CVE-2017-18269",
"value": "CVE-2017-18269",
"url": "https://security-tracker.debian.org/tracker/CVE-2017-18269"
}
],
"links": [
{
"url": "https://security-tracker.debian.org/tracker/CVE-2017-18269"
}
]
},
{
"category": "cluster_image_scanning",
"message": "CVE-2017-16997 in glibc",
"description": "elf/dl-load.c in the GNU C Library (aka glibc or libc6) 2.19 through 2.26 mishandles RPATH and RUNPATH containing $ORIGIN for a privileged (setuid or AT_SECURE) program, which allows local users to gain privileges via a Trojan horse library in the current working directory, related to the fillin_rpath and decompose_rpath functions. This is associated with misinterpretion of an empty RPATH/RUNPATH token as the \"./\" directory. NOTE: this configuration of RPATH/RUNPATH for a privileged program is apparently very uncommon; most likely, no such program is shipped with any common Linux distribution.",
"cve": "debian:9:glibc:CVE-2017-16997",
"severity": "Critical",
"confidence": "Unknown",
"solution": "Upgrade glibc from 2.24-11+deb9u3 to 2.24-11+deb9u4",
"scanner": {
"id": "starboard",
"name": "Starboard"
},
"location": {
"dependency": {
"package": {
"name": "glibc"
},
"version": "2.24-11+deb9u3"
},
"operating_system": "debian:9",
"image": "registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256:bc09fe2e0721dfaeee79364115aeedf2174cce0947b9ae5fe7c33312ee019a4e"
},
"identifiers": [
{
"type": "cve",
"name": "CVE-2017-16997",
"value": "CVE-2017-16997",
"url": "https://security-tracker.debian.org/tracker/CVE-2017-16997"
}
],
"links": [
{
"url": "https://security-tracker.debian.org/tracker/CVE-2017-16997"
}
]
}
],
"remediations": [],
"scan": {
"scanner": {
"id": "starboard",
"name": "Starboard",
"url": "https://github.com/aquasecurity/starboard",
"vendor": {
"name": "GitLab"
},
"version": "0.10.0"
},
"type": "cluster_image_scanning",
"status": "success"
}
}
...@@ -39,6 +39,15 @@ RSpec.describe Gitlab::Vulnerabilities::Parser do ...@@ -39,6 +39,15 @@ RSpec.describe Gitlab::Vulnerabilities::Parser do
end end
end end
context 'with cluster image scanning as category' do
it 'returns a Scanning Vulnerability' do
params[:category] = 'cluster_image_scanning'
expect(subject).to be_a(Gitlab::Vulnerabilities::ContainerScanningVulnerability)
expect(subject.target_branch).to eq('master')
end
end
context 'with an invalid category' do context 'with an invalid category' do
it 'raises an exception' do it 'raises an exception' do
params[:category] = 'foo' params[:category] = 'foo'
......
...@@ -109,7 +109,7 @@ RSpec.describe Ci::Pipeline do ...@@ -109,7 +109,7 @@ RSpec.describe Ci::Pipeline do
subject { pipeline.security_reports } subject { pipeline.security_reports }
before do before do
stub_licensed_features(sast: true, dependency_scanning: true, container_scanning: true) stub_licensed_features(sast: true, dependency_scanning: true, container_scanning: true, cluster_image_scanning: true)
end end
context 'when pipeline has multiple builds with security reports' do context 'when pipeline has multiple builds with security reports' do
...@@ -119,12 +119,16 @@ RSpec.describe Ci::Pipeline do ...@@ -119,12 +119,16 @@ RSpec.describe Ci::Pipeline do
let(:build_ds_2) { create(:ci_build, :success, name: 'ds_2', pipeline: pipeline, project: project) } let(:build_ds_2) { create(:ci_build, :success, name: 'ds_2', pipeline: pipeline, project: project) }
let(:build_cs_1) { create(:ci_build, :success, name: 'cs_1', pipeline: pipeline, project: project) } let(:build_cs_1) { create(:ci_build, :success, name: 'cs_1', pipeline: pipeline, project: project) }
let(:build_cs_2) { create(:ci_build, :success, name: 'cs_2', pipeline: pipeline, project: project) } let(:build_cs_2) { create(:ci_build, :success, name: 'cs_2', pipeline: pipeline, project: project) }
let(:build_cis_1) { create(:ci_build, :success, name: 'cis_1', pipeline: pipeline, project: project) }
let(:build_cis_2) { create(:ci_build, :success, name: 'cis_2', pipeline: pipeline, project: project) }
let!(:sast1_artifact) { create(:ee_ci_job_artifact, :sast, job: build_sast_1, project: project) } let!(:sast1_artifact) { create(:ee_ci_job_artifact, :sast, job: build_sast_1, project: project) }
let!(:sast2_artifact) { create(:ee_ci_job_artifact, :sast, job: build_sast_2, project: project) } let!(:sast2_artifact) { create(:ee_ci_job_artifact, :sast, job: build_sast_2, project: project) }
let!(:ds1_artifact) { create(:ee_ci_job_artifact, :dependency_scanning, job: build_ds_1, project: project) } let!(:ds1_artifact) { create(:ee_ci_job_artifact, :dependency_scanning, job: build_ds_1, project: project) }
let!(:ds2_artifact) { create(:ee_ci_job_artifact, :dependency_scanning, job: build_ds_2, project: project) } let!(:ds2_artifact) { create(:ee_ci_job_artifact, :dependency_scanning, job: build_ds_2, project: project) }
let!(:cs1_artifact) { create(:ee_ci_job_artifact, :container_scanning, job: build_cs_1, project: project) } let!(:cs1_artifact) { create(:ee_ci_job_artifact, :container_scanning, job: build_cs_1, project: project) }
let!(:cs2_artifact) { create(:ee_ci_job_artifact, :container_scanning, job: build_cs_2, project: project) } let!(:cs2_artifact) { create(:ee_ci_job_artifact, :container_scanning, job: build_cs_2, project: project) }
let!(:cis1_artifact) { create(:ee_ci_job_artifact, :cluster_image_scanning, job: build_cis_1, project: project) }
let!(:cis2_artifact) { create(:ee_ci_job_artifact, :cluster_image_scanning, job: build_cis_2, project: project) }
it 'assigns pipeline to the reports' do it 'assigns pipeline to the reports' do
expect(subject.pipeline).to eq(pipeline) expect(subject.pipeline).to eq(pipeline)
...@@ -132,12 +136,13 @@ RSpec.describe Ci::Pipeline do ...@@ -132,12 +136,13 @@ RSpec.describe Ci::Pipeline do
end end
it 'returns security reports with collected data grouped as expected' do it 'returns security reports with collected data grouped as expected' do
expect(subject.reports.keys).to contain_exactly('sast', 'dependency_scanning', 'container_scanning') expect(subject.reports.keys).to contain_exactly('sast', 'dependency_scanning', 'container_scanning', 'cluster_image_scanning')
# for each of report categories, we have merged 2 reports with the same data (fixture) # for each of report categories, we have merged 2 reports with the same data (fixture)
expect(subject.get_report('sast', sast1_artifact).findings.size).to eq(5) expect(subject.get_report('sast', sast1_artifact).findings.size).to eq(5)
expect(subject.get_report('dependency_scanning', ds1_artifact).findings.size).to eq(4) expect(subject.get_report('dependency_scanning', ds1_artifact).findings.size).to eq(4)
expect(subject.get_report('container_scanning', cs1_artifact).findings.size).to eq(8) expect(subject.get_report('container_scanning', cs1_artifact).findings.size).to eq(8)
expect(subject.get_report('cluster_image_scanning', cis1_artifact).findings.size).to eq(2)
end end
context 'when builds are retried' do context 'when builds are retried' do
...@@ -147,6 +152,7 @@ RSpec.describe Ci::Pipeline do ...@@ -147,6 +152,7 @@ RSpec.describe Ci::Pipeline do
expect(subject.get_report('sast', sast1_artifact).findings.size).to eq(5) expect(subject.get_report('sast', sast1_artifact).findings.size).to eq(5)
expect(subject.get_report('dependency_scanning', ds1_artifact).findings.size).to eq(4) expect(subject.get_report('dependency_scanning', ds1_artifact).findings.size).to eq(4)
expect(subject.get_report('container_scanning', cs1_artifact).findings.size).to eq(8) expect(subject.get_report('container_scanning', cs1_artifact).findings.size).to eq(8)
expect(subject.get_report('cluster_image_scanning', cis1_artifact).findings.size).to eq(2)
end end
end end
...@@ -535,18 +541,22 @@ RSpec.describe Ci::Pipeline do ...@@ -535,18 +541,22 @@ RSpec.describe Ci::Pipeline do
where(:pipeline_status, :build_types, :expected_status) do where(:pipeline_status, :build_types, :expected_status) do
[ [
[:blocked, [:container_scanning], false], [:blocked, [:container_scanning], false],
[:blocked, [:cluster_image_scanning], false],
[:blocked, [:license_scan_v2_1, :container_scanning], true], [:blocked, [:license_scan_v2_1, :container_scanning], true],
[:blocked, [:license_scan_v2_1], true], [:blocked, [:license_scan_v2_1], true],
[:blocked, [], false], [:blocked, [], false],
[:failed, [:container_scanning], false], [:failed, [:container_scanning], false],
[:failed, [:cluster_image_scanning], false],
[:failed, [:license_scan_v2_1, :container_scanning], true], [:failed, [:license_scan_v2_1, :container_scanning], true],
[:failed, [:license_scan_v2_1], true], [:failed, [:license_scan_v2_1], true],
[:failed, [], false], [:failed, [], false],
[:running, [:container_scanning], false], [:running, [:container_scanning], false],
[:running, [:cluster_image_scanning], false],
[:running, [:license_scan_v2_1, :container_scanning], true], [:running, [:license_scan_v2_1, :container_scanning], true],
[:running, [:license_scan_v2_1], true], [:running, [:license_scan_v2_1], true],
[:running, [], false], [:running, [], false],
[:success, [:container_scanning], false], [:success, [:container_scanning], false],
[:success, [:cluster_image_scanning], false],
[:success, [:license_scan_v2_1, :container_scanning], true], [:success, [:license_scan_v2_1, :container_scanning], true],
[:success, [:license_scan_v2_1], true], [:success, [:license_scan_v2_1], true],
[:success, [], false] [:success, [], false]
......
...@@ -31,6 +31,14 @@ RSpec.describe Ci::JobArtifact do ...@@ -31,6 +31,14 @@ RSpec.describe Ci::JobArtifact do
it { is_expected.to eq([artifact]) } it { is_expected.to eq([artifact]) }
end end
describe '.cluster_image_scanning_reports' do
subject { Ci::JobArtifact.cluster_image_scanning_reports }
let_it_be(:artifact) { create(:ee_ci_job_artifact, :cluster_image_scanning) }
it { is_expected.to eq([artifact]) }
end
describe '.metrics_reports' do describe '.metrics_reports' do
subject { Ci::JobArtifact.metrics_reports } subject { Ci::JobArtifact.metrics_reports }
...@@ -226,13 +234,14 @@ RSpec.describe Ci::JobArtifact do ...@@ -226,13 +234,14 @@ RSpec.describe Ci::JobArtifact do
context 'for different types' do context 'for different types' do
where(:file_type, :security_report?) do where(:file_type, :security_report?) do
:performance | false :performance | false
:sast | true :sast | true
:secret_detection | true :secret_detection | true
:dependency_scanning | true :dependency_scanning | true
:container_scanning | true :container_scanning | true
:dast | true :cluster_image_scanning | true
:coverage_fuzzing | true :dast | true
:coverage_fuzzing | true
end end
with_them do with_them do
......
...@@ -1314,7 +1314,7 @@ RSpec.describe Namespace do ...@@ -1314,7 +1314,7 @@ RSpec.describe Namespace do
subject { namespace.store_security_reports_available? } subject { namespace.store_security_reports_available? }
context 'when at least one security report feature is enabled' do context 'when at least one security report feature is enabled' do
where(report_type: [:sast, :secret_detection, :dast, :dependency_scanning, :container_scanning]) where(report_type: [:sast, :secret_detection, :dast, :dependency_scanning, :container_scanning, :cluster_image_scanning])
with_them do with_them do
before do before do
......
...@@ -110,6 +110,45 @@ RSpec.describe 'Query.vulnerabilities.location' do ...@@ -110,6 +110,45 @@ RSpec.describe 'Query.vulnerabilities.location' do
end end
end end
context 'when the vulnerability was found by a cluster image scan' do
let_it_be(:vulnerability) do
create(:vulnerability, project: project, report_type: :cluster_image_scanning)
end
let_it_be(:metadata) do
{
location: {
image: 'vulnerable_image',
operating_system: 'vulnerable_os',
dependency: {
version: '6.6.6',
package: {
name: 'vulnerable_container'
}
}
}
}
end
let_it_be(:finding) do
create(
:vulnerabilities_finding,
vulnerability: vulnerability,
raw_metadata: metadata.to_json
)
end
it 'returns a container location' do
location = subject.first['location']
expect(location['__typename']).to eq('VulnerabilityLocationContainerScanning')
expect(location['image']).to eq('vulnerable_image')
expect(location['operatingSystem']).to eq('vulnerable_os')
expect(location['dependency']['version']).to eq('6.6.6')
expect(location['dependency']['package']['name']).to eq('vulnerable_container')
end
end
context 'when the vulnerability was found by a dependency scan' do context 'when the vulnerability was found by a dependency scan' do
let_it_be(:vulnerability) do let_it_be(:vulnerability) do
create(:vulnerability, project: project, report_type: :dependency_scanning) create(:vulnerability, project: project, report_type: :dependency_scanning)
......
...@@ -56,7 +56,7 @@ RSpec.describe StoreSecurityReportsWorker do ...@@ -56,7 +56,7 @@ RSpec.describe StoreSecurityReportsWorker do
end end
context 'when at least one security report feature is enabled' do context 'when at least one security report feature is enabled' do
where(report_type: [:sast, :dast, :dependency_scanning, :container_scanning]) where(report_type: [:sast, :dast, :dependency_scanning, :container_scanning, :cluster_image_scanning])
with_them do with_them do
before do before do
......
...@@ -15,7 +15,7 @@ module Gitlab ...@@ -15,7 +15,7 @@ module Gitlab
%i[junit codequality sast secret_detection dependency_scanning container_scanning %i[junit codequality sast secret_detection dependency_scanning container_scanning
dast performance browser_performance load_performance license_scanning metrics lsif dast performance browser_performance load_performance license_scanning metrics lsif
dotenv cobertura terraform accessibility cluster_applications dotenv cobertura terraform accessibility cluster_applications
requirements coverage_fuzzing api_fuzzing].freeze requirements coverage_fuzzing api_fuzzing cluster_image_scanning].freeze
attributes ALLOWED_KEYS attributes ALLOWED_KEYS
...@@ -32,6 +32,7 @@ module Gitlab ...@@ -32,6 +32,7 @@ module Gitlab
validates :secret_detection, array_of_strings_or_string: true validates :secret_detection, array_of_strings_or_string: true
validates :dependency_scanning, array_of_strings_or_string: true validates :dependency_scanning, array_of_strings_or_string: true
validates :container_scanning, array_of_strings_or_string: true validates :container_scanning, array_of_strings_or_string: true
validates :cluster_image_scanning, array_of_strings_or_string: true
validates :dast, array_of_strings_or_string: true validates :dast, array_of_strings_or_string: true
validates :performance, array_of_strings_or_string: true validates :performance, array_of_strings_or_string: true
validates :browser_performance, array_of_strings_or_string: true validates :browser_performance, array_of_strings_or_string: true
......
...@@ -508,6 +508,14 @@ FactoryBot.define do ...@@ -508,6 +508,14 @@ FactoryBot.define do
end end
end end
trait :cluster_image_scanning do
options do
{
artifacts: { reports: { cluster_image_scanning: 'gl-cluster-image-scanning-report.json' } }
}
end
end
trait :license_scanning do trait :license_scanning do
options do options do
{ {
......
...@@ -40,6 +40,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Reports do ...@@ -40,6 +40,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Reports do
:secret_detection | 'gl-secret-detection-report.json' :secret_detection | 'gl-secret-detection-report.json'
:dependency_scanning | 'gl-dependency-scanning-report.json' :dependency_scanning | 'gl-dependency-scanning-report.json'
:container_scanning | 'gl-container-scanning-report.json' :container_scanning | 'gl-container-scanning-report.json'
:cluster_image_scanning | 'gl-cluster-image-scanning-report.json'
:dast | 'gl-dast-report.json' :dast | 'gl-dast-report.json'
:license_scanning | 'gl-license-scanning-report.json' :license_scanning | 'gl-license-scanning-report.json'
:performance | 'performance.json' :performance | 'performance.json'
......
...@@ -39,7 +39,7 @@ RSpec.describe Ci::RetryBuildService do ...@@ -39,7 +39,7 @@ RSpec.describe Ci::RetryBuildService do
erased_at auto_canceled_by job_artifacts job_artifacts_archive erased_at auto_canceled_by job_artifacts job_artifacts_archive
job_artifacts_metadata job_artifacts_trace job_artifacts_junit job_artifacts_metadata job_artifacts_trace job_artifacts_junit
job_artifacts_sast job_artifacts_secret_detection job_artifacts_dependency_scanning job_artifacts_sast job_artifacts_secret_detection job_artifacts_dependency_scanning
job_artifacts_container_scanning job_artifacts_dast job_artifacts_container_scanning job_artifacts_cluster_image_scanning job_artifacts_dast
job_artifacts_license_scanning job_artifacts_license_scanning
job_artifacts_performance job_artifacts_browser_performance job_artifacts_load_performance job_artifacts_performance job_artifacts_browser_performance job_artifacts_load_performance
job_artifacts_lsif job_artifacts_terraform job_artifacts_cluster_applications job_artifacts_lsif job_artifacts_terraform job_artifacts_cluster_applications
......
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