Commit 5caa90d0 authored by Michał Zając's avatar Michał Zając Committed by Matthias Käppler

Log deprecated/unsupported report schema versions

Log when a deprecated or unsupported report schema version is used by
the scanner.

Changelog: changed
EE: true
parent a1d2b629
...@@ -48,7 +48,7 @@ module Security ...@@ -48,7 +48,7 @@ module Security
def security_scan def security_scan
@security_scan ||= Security::Scan.safe_find_or_create_by!(build: job, scan_type: artifact.file_type) do |scan| @security_scan ||= Security::Scan.safe_find_or_create_by!(build: job, scan_type: artifact.file_type) do |scan|
scan.processing_errors = security_report.errors.map(&:stringify_keys) if security_report.errored? scan.processing_errors = security_report.errors.map(&:stringify_keys) if security_report.errored?
scan.processing_warnings = security_report.warnings.map(&:stringify_keys) scan.processing_warnings = security_report.warnings.map(&:stringify_keys) if security_report.warnings?
scan.status = initial_scan_status scan.status = initial_scan_status
end end
end end
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
let_it_be(:project) { create(:project) }
using RSpec::Parameterized::TableSyntax using RSpec::Parameterized::TableSyntax
where(:report_type, :expected_errors, :expected_warnings, :valid_data) do where(:report_type, :expected_errors, :expected_warnings, :valid_data) do
...@@ -15,7 +17,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do ...@@ -15,7 +17,7 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
end end
with_them do with_them do
let(:validator) { described_class.new(report_type, report_data, valid_data['version']) } let(:validator) { described_class.new(report_type, report_data, valid_data['version'], project: project) }
describe '#valid?' do describe '#valid?' do
subject { validator.valid? } subject { validator.valid? }
...@@ -33,20 +35,64 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do ...@@ -33,20 +35,64 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
end end
end end
describe '#deprecation_warnings' do
subject { validator.deprecation_warnings }
let(:supported_versions) { described_class::SUPPORTED_VERSIONS[report_type].join(", ") }
context 'when report uses a deprecated version' do
let(:report_data) { valid_data }
let(:expected_deprecation_warnings_array) do
[
"Version 10.0.0 for report type #{report_type} has been deprecated, supported versions for this report type are: #{supported_versions}"
]
end
it { is_expected.to eq(expected_deprecation_warnings_array) }
end
context 'when report uses a supported version' do
let(:supported_version) { described_class::SUPPORTED_VERSIONS[report_type].first }
let(:report_data) do
valid_data['version'] = supported_version
valid_data
end
it { is_expected.to eq([]) }
end
end
describe '#warnings' do describe '#warnings' do
subject { validator.warnings } subject { validator.warnings }
context 'when given data is valid according to the schema' do context 'when given data is valid according to the schema' do
let(:report_data) { valid_data } let(:report_data) { valid_data }
let(:supported_version) { described_class::SUPPORTED_VERSIONS[report_type].join(", ") } let(:supported_version) { described_class::SUPPORTED_VERSIONS[report_type].join(", ") }
let(:expected_warnings_array) do let(:expected_warnings_array) { [] }
[
"Version 10.0.0 for report type #{report_type} has been deprecated, supported versions for this report type are: #{supported_version}"
]
end
it { is_expected.to eq(expected_warnings) } it { is_expected.to eq(expected_warnings) }
end end
context 'when given data is invalid according to the schema' do
let(:report_data) { { 'version' => '10.0.0' } }
context 'and enforce_security_report_validation is enabled' do
before do
stub_feature_flags(enforce_security_report_validation: project)
end
it { is_expected.to be_empty }
end
context 'and enforce_security_report_validation is disabled' do
before do
stub_feature_flags(enforce_security_report_validation: false)
end
it { is_expected.to eq(expected_errors) }
end
end
end end
describe '#errors' do describe '#errors' do
...@@ -54,7 +100,21 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do ...@@ -54,7 +100,21 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
subject { validator.errors } subject { validator.errors }
it { is_expected.to eq(expected_errors) } context 'when enforce_security_report_validation is enabled' do
before do
stub_feature_flags(enforce_security_report_validation: project)
end
it { is_expected.to eq(expected_errors) }
end
context 'when enforce_security_report_validation is disabled' do
before do
stub_feature_flags(enforce_security_report_validation: false)
end
it { is_expected.to be_empty }
end
end end
end end
end end
...@@ -158,6 +158,20 @@ RSpec.describe Security::StoreScanService do ...@@ -158,6 +158,20 @@ RSpec.describe Security::StoreScanService do
expect(Security::StoreFindingsMetadataService).to have_received(:execute) expect(Security::StoreFindingsMetadataService).to have_received(:execute)
end end
context 'when the report has no warnings' do
before do
artifact.security_report.warnings = []
end
let(:security_scan) { Security::Scan.last }
it 'does not store an empty array' do
store_scan
expect(security_scan.info).to eq({})
end
end
context 'when the report has some warnings' do context 'when the report has some warnings' do
before do before do
artifact.security_report.warnings << { 'type' => 'foo', 'message' => 'bar' } artifact.security_report.warnings << { 'type' => 'foo', 'message' => 'bar' }
......
...@@ -14,6 +14,7 @@ module Gitlab ...@@ -14,6 +14,7 @@ module Gitlab
def initialize(json_data, report, vulnerability_finding_signatures_enabled = false, validate: false) def initialize(json_data, report, vulnerability_finding_signatures_enabled = false, validate: false)
@json_data = json_data @json_data = json_data
@report = report @report = report
@project = report.project
@validate = validate @validate = validate
@vulnerability_finding_signatures_enabled = vulnerability_finding_signatures_enabled @vulnerability_finding_signatures_enabled = vulnerability_finding_signatures_enabled
end end
...@@ -51,22 +52,27 @@ module Gitlab ...@@ -51,22 +52,27 @@ module Gitlab
# #
# After 15.0 we will enforce schema validation by default # After 15.0 we will enforce schema validation by default
# See: https://gitlab.com/groups/gitlab-org/-/epics/6968 # See: https://gitlab.com/groups/gitlab-org/-/epics/6968
schema_validation_passed = schema_validator.valid? schema_validator.deprecation_warnings.each { |deprecation_warning| report.add_warning('Schema', deprecation_warning) }
if validate if validate
schema_validator.errors.each { |error| report.add_error('Schema', error) } unless schema_validation_passed schema_validation_passed = schema_validator.valid?
# Validation warnings are errors
schema_validator.errors.each { |error| report.add_error('Schema', error) }
schema_validator.warnings.each { |warning| report.add_error('Schema', warning) }
schema_validation_passed schema_validation_passed
else else
# We treat all schema validation errors as warnings # Validation warnings are warnings
schema_validator.errors.each { |error| report.add_warning('Schema', error) } schema_validator.errors.each { |error| report.add_warning('Schema', error) }
schema_validator.warnings.each { |warning| report.add_warning('Schema', warning) }
true true
end end
end end
def schema_validator def schema_validator
@schema_validator ||= ::Gitlab::Ci::Parsers::Security::Validators::SchemaValidator.new(report.type, report_data, report.version) @schema_validator ||= ::Gitlab::Ci::Parsers::Security::Validators::SchemaValidator.new(report.type, report_data, report.version, project: @project)
end end
def report_data def report_data
...@@ -136,7 +142,7 @@ module Gitlab ...@@ -136,7 +142,7 @@ module Gitlab
metadata_version: report_version, metadata_version: report_version,
details: data['details'] || {}, details: data['details'] || {},
signatures: signatures, signatures: signatures,
project_id: report.project_id, project_id: @project.id,
vulnerability_finding_signatures_enabled: @vulnerability_finding_signatures_enabled)) vulnerability_finding_signatures_enabled: @vulnerability_finding_signatures_enabled))
end end
...@@ -279,7 +285,7 @@ module Gitlab ...@@ -279,7 +285,7 @@ module Gitlab
report_type: report.type, report_type: report.type,
primary_identifier_fingerprint: primary_identifier&.fingerprint, primary_identifier_fingerprint: primary_identifier&.fingerprint,
location_fingerprint: location_fingerprint, location_fingerprint: location_fingerprint,
project_id: report.project_id project_id: @project.id
} }
if uuid_v5_name_components.values.any?(&:nil?) if uuid_v5_name_components.values.any?(&:nil?)
......
...@@ -26,19 +26,19 @@ module Gitlab ...@@ -26,19 +26,19 @@ module Gitlab
8.0.0-rc1 8.0.1-rc1 8.1.0-rc1 9.0.0-rc1].freeze 8.0.0-rc1 8.0.1-rc1 8.1.0-rc1 9.0.0-rc1].freeze
# These come from https://app.periscopedata.com/app/gitlab/895813/Secure-Scan-metrics?widget=12248944&udv=1385516 # These come from https://app.periscopedata.com/app/gitlab/895813/Secure-Scan-metrics?widget=12248944&udv=1385516
KNOWN_VERSIONS_TO_DEPRECATE = %w[0.1 1.0 1.0.0 1.2 1.3 10.0.0 12.1.0 13.1.0 2.0 2.1 2.1.0 2.3 2.3.0 2.4 3.0 3.0.0 3.0.6 3.13.2 V2.7.0].freeze KNOWN_VERSIONS_TO_REMOVE = %w[0.1 1.0 1.0.0 1.2 1.3 10.0.0 12.1.0 13.1.0 2.0 2.1 2.1.0 2.3 2.3.0 2.4 3.0 3.0.0 3.0.6 3.13.2 V2.7.0].freeze
VERSIONS_TO_DEPRECATE_IN_15_0 = (PREVIOUS_RELEASES + KNOWN_VERSIONS_TO_DEPRECATE).freeze VERSIONS_TO_REMOVE_IN_15_0 = (PREVIOUS_RELEASES + KNOWN_VERSIONS_TO_REMOVE).freeze
DEPRECATED_VERSIONS = { DEPRECATED_VERSIONS = {
cluster_image_scanning: VERSIONS_TO_DEPRECATE_IN_15_0, cluster_image_scanning: VERSIONS_TO_REMOVE_IN_15_0,
container_scanning: VERSIONS_TO_DEPRECATE_IN_15_0, container_scanning: VERSIONS_TO_REMOVE_IN_15_0,
coverage_fuzzing: VERSIONS_TO_DEPRECATE_IN_15_0, coverage_fuzzing: VERSIONS_TO_REMOVE_IN_15_0,
dast: VERSIONS_TO_DEPRECATE_IN_15_0, dast: VERSIONS_TO_REMOVE_IN_15_0,
api_fuzzing: VERSIONS_TO_DEPRECATE_IN_15_0, api_fuzzing: VERSIONS_TO_REMOVE_IN_15_0,
dependency_scanning: VERSIONS_TO_DEPRECATE_IN_15_0, dependency_scanning: VERSIONS_TO_REMOVE_IN_15_0,
sast: VERSIONS_TO_DEPRECATE_IN_15_0, sast: VERSIONS_TO_REMOVE_IN_15_0,
secret_detection: VERSIONS_TO_DEPRECATE_IN_15_0 secret_detection: VERSIONS_TO_REMOVE_IN_15_0
}.freeze }.freeze
class Schema class Schema
...@@ -86,15 +86,18 @@ module Gitlab ...@@ -86,15 +86,18 @@ module Gitlab
end end
end end
def initialize(report_type, report_data, report_version = nil) def initialize(report_type, report_data, report_version = nil, project: nil)
@report_type = report_type&.to_sym @report_type = report_type&.to_sym
@report_data = report_data @report_data = report_data
@report_version = report_version @report_version = report_version
@project = project
@errors = [] @errors = []
@warnings = [] @warnings = []
@deprecation_warnings = []
populate_errors populate_errors
populate_warnings populate_warnings
populate_deprecation_warnings
end end
def valid? def valid?
...@@ -102,25 +105,46 @@ module Gitlab ...@@ -102,25 +105,46 @@ module Gitlab
end end
def populate_errors def populate_errors
if Feature.enabled?(:enforce_security_report_validation) schema_validation_errors = schema.validate(report_data).map { |error| JSONSchemer::Errors.pretty(error) }
@errors += schema.validate(report_data).map { |error| JSONSchemer::Errors.pretty(error) }
log_warnings(problem_type: 'schema_validation_fails') unless schema_validation_errors.empty?
if Feature.enabled?(:enforce_security_report_validation, @project)
@errors += schema_validation_errors
else else
@warnings += schema.validate(report_data).map { |error| JSONSchemer::Errors.pretty(error) } @warnings += schema_validation_errors
end end
end end
def populate_warnings def populate_warnings
add_deprecated_report_version_message if report_uses_deprecated_schema_version?
add_unsupported_report_version_message if !report_uses_supported_schema_version? && !report_uses_deprecated_schema_version? add_unsupported_report_version_message if !report_uses_supported_schema_version? && !report_uses_deprecated_schema_version?
end end
def populate_deprecation_warnings
add_deprecated_report_version_message if report_uses_deprecated_schema_version?
end
def add_deprecated_report_version_message def add_deprecated_report_version_message
log_warnings(problem_type: 'using_deprecated_schema_version')
message = "Version #{report_version} for report type #{report_type} has been deprecated, supported versions for this report type are: #{supported_schema_versions}" message = "Version #{report_version} for report type #{report_type} has been deprecated, supported versions for this report type are: #{supported_schema_versions}"
add_message_as(level: :warning, message: message) add_message_as(level: :deprecation_warning, message: message)
end
def log_warnings(problem_type:)
Gitlab::AppLogger.info(
message: 'security report schema validation problem',
security_report_type: report_type,
security_report_version: report_version,
project_id: @project.id,
security_report_failure: problem_type
)
end end
def add_unsupported_report_version_message def add_unsupported_report_version_message
if Feature.enabled?(:enforce_security_report_validation) log_warnings(problem_type: 'using_unsupported_schema_version')
if Feature.enabled?(:enforce_security_report_validation, @project)
handle_unsupported_report_version(treat_as: :error) handle_unsupported_report_version(treat_as: :error)
else else
handle_unsupported_report_version(treat_as: :warning) handle_unsupported_report_version(treat_as: :warning)
...@@ -152,6 +176,8 @@ module Gitlab ...@@ -152,6 +176,8 @@ module Gitlab
def add_message_as(level:, message:) def add_message_as(level:, message:)
case level case level
when :deprecation_warning
@deprecation_warnings << message
when :error when :error
@errors << message @errors << message
when :warning when :warning
...@@ -159,7 +185,7 @@ module Gitlab ...@@ -159,7 +185,7 @@ module Gitlab
end end
end end
attr_reader :errors, :warnings attr_reader :errors, :warnings, :deprecation_warnings
private private
......
...@@ -9,6 +9,7 @@ module Gitlab ...@@ -9,6 +9,7 @@ module Gitlab
attr_accessor :scan, :scanned_resources, :errors, :analyzer, :version, :schema_validation_status, :warnings attr_accessor :scan, :scanned_resources, :errors, :analyzer, :version, :schema_validation_status, :warnings
delegate :project_id, to: :pipeline delegate :project_id, to: :pipeline
delegate :project, to: :pipeline
def initialize(type, pipeline, created_at) def initialize(type, pipeline, created_at)
@type = type @type = type
...@@ -38,6 +39,10 @@ module Gitlab ...@@ -38,6 +39,10 @@ module Gitlab
errors.present? errors.present?
end end
def warnings?
warnings.present?
end
def add_scanner(scanner) def add_scanner(scanner)
scanners[scanner.key] ||= scanner scanners[scanner.key] ||= scanner
end end
......
...@@ -42,11 +42,13 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do ...@@ -42,11 +42,13 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
let(:validate) { false } let(:validate) { false }
let(:valid?) { false } let(:valid?) { false }
let(:errors) { ['foo'] } let(:errors) { ['foo'] }
let(:warnings) { ['bar'] }
before do before do
allow_next_instance_of(validator_class) do |instance| allow_next_instance_of(validator_class) do |instance|
allow(instance).to receive(:valid?).and_return(valid?) allow(instance).to receive(:valid?).and_return(valid?)
allow(instance).to receive(:errors).and_return(errors) allow(instance).to receive(:errors).and_return(errors)
allow(instance).to receive(:warnings).and_return(warnings)
end end
allow(parser).to receive_messages(create_scanner: true, create_scan: true) allow(parser).to receive_messages(create_scanner: true, create_scan: true)
...@@ -55,12 +57,17 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do ...@@ -55,12 +57,17 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
it 'instantiates the validator with correct params' do it 'instantiates the validator with correct params' do
parse_report parse_report
expect(validator_class).to have_received(:new).with(report.type, {}, report.version) expect(validator_class).to have_received(:new).with(report.type, {}, report.version, project: pipeline.project)
end end
context 'when the report data is not valid according to the schema' do context 'when the report data is not valid according to the schema' do
it 'adds warnings to the report' do it 'adds warnings to the report' do
expect { parse_report }.to change { report.warnings }.from([]).to([{ message: 'foo', type: 'Schema' }]) expect { parse_report }.to change { report.warnings }.from([]).to(
[
{ message: 'foo', type: 'Schema' },
{ message: 'bar', type: 'Schema' }
]
)
end end
it 'keeps the execution flow as normal' do it 'keeps the execution flow as normal' do
...@@ -74,11 +81,16 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do ...@@ -74,11 +81,16 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
context 'when the report data is valid according to the schema' do context 'when the report data is valid according to the schema' do
let(:valid?) { true } let(:valid?) { true }
let(:errors) { [] } let(:errors) { [] }
let(:warnings) { [] }
it 'does not add warnings to the report' do it 'does not add errors to the report' do
expect { parse_report }.not_to change { report.errors } expect { parse_report }.not_to change { report.errors }
end end
it 'does not add warnings to the report' do
expect { parse_report }.not_to change { report.warnings }
end
it 'keeps the execution flow as normal' do it 'keeps the execution flow as normal' do
parse_report parse_report
...@@ -92,11 +104,13 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do ...@@ -92,11 +104,13 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
let(:validate) { true } let(:validate) { true }
let(:valid?) { false } let(:valid?) { false }
let(:errors) { ['foo'] } let(:errors) { ['foo'] }
let(:warnings) { ['bar'] }
before do before do
allow_next_instance_of(validator_class) do |instance| allow_next_instance_of(validator_class) do |instance|
allow(instance).to receive(:valid?).and_return(valid?) allow(instance).to receive(:valid?).and_return(valid?)
allow(instance).to receive(:errors).and_return(errors) allow(instance).to receive(:errors).and_return(errors)
allow(instance).to receive(:warnings).and_return(warnings)
end end
allow(parser).to receive_messages(create_scanner: true, create_scan: true) allow(parser).to receive_messages(create_scanner: true, create_scan: true)
...@@ -105,12 +119,17 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do ...@@ -105,12 +119,17 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
it 'instantiates the validator with correct params' do it 'instantiates the validator with correct params' do
parse_report parse_report
expect(validator_class).to have_received(:new).with(report.type, {}, report.version) expect(validator_class).to have_received(:new).with(report.type, {}, report.version, project: pipeline.project)
end end
context 'when the report data is not valid according to the schema' do context 'when the report data is not valid according to the schema' do
it 'adds errors to the report' do it 'adds errors to the report' do
expect { parse_report }.to change { report.errors }.from([]).to([{ message: 'foo', type: 'Schema' }]) expect { parse_report }.to change { report.errors }.from([]).to(
[
{ message: 'foo', type: 'Schema' },
{ message: 'bar', type: 'Schema' }
]
)
end end
it 'does not try to create report entities' do it 'does not try to create report entities' do
...@@ -124,11 +143,16 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do ...@@ -124,11 +143,16 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
context 'when the report data is valid according to the schema' do context 'when the report data is valid according to the schema' do
let(:valid?) { true } let(:valid?) { true }
let(:errors) { [] } let(:errors) { [] }
let(:warnings) { [] }
it 'does not add errors to the report' do it 'does not add errors to the report' do
expect { parse_report }.not_to change { report.errors }.from([]) expect { parse_report }.not_to change { report.errors }.from([])
end end
it 'does not add warnings to the report' do
expect { parse_report }.not_to change { report.warnings }.from([])
end
it 'keeps the execution flow as normal' do it 'keeps the execution flow as normal' do
parse_report parse_report
......
...@@ -3,7 +3,9 @@ ...@@ -3,7 +3,9 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
let(:validator) { described_class.new(report_type, report_data, report_version) } let_it_be(:project) { create(:project) }
let(:validator) { described_class.new(report_type, report_data, report_version, project: project) }
describe 'SUPPORTED_VERSIONS' do describe 'SUPPORTED_VERSIONS' do
schema_path = Rails.root.join("lib", "gitlab", "ci", "parsers", "security", "validators", "schemas") schema_path = Rails.root.join("lib", "gitlab", "ci", "parsers", "security", "validators", "schemas")
...@@ -75,6 +77,18 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do ...@@ -75,6 +77,18 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
end end
it { is_expected.to be_falsey } it { is_expected.to be_falsey }
it 'logs related information' do
expect(Gitlab::AppLogger).to receive(:info).with(
message: "security report schema validation problem",
security_report_type: report_type,
security_report_version: report_version,
project_id: project.id,
security_report_failure: 'schema_validation_fails'
)
subject
end
end end
end end
...@@ -91,6 +105,18 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do ...@@ -91,6 +105,18 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
end end
it { is_expected.to be_truthy } it { is_expected.to be_truthy }
it 'logs related information' do
expect(Gitlab::AppLogger).to receive(:info).with(
message: "security report schema validation problem",
security_report_type: report_type,
security_report_version: report_version,
project_id: project.id,
security_report_failure: 'using_deprecated_schema_version'
)
subject
end
end end
context 'and the report does not pass schema validation' do context 'and the report does not pass schema validation' do
...@@ -142,6 +168,18 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do ...@@ -142,6 +168,18 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
end end
it { is_expected.to be_falsey } it { is_expected.to be_falsey }
it 'logs related information' do
expect(Gitlab::AppLogger).to receive(:info).with(
message: "security report schema validation problem",
security_report_type: report_type,
security_report_version: report_version,
project_id: project.id,
security_report_failure: 'using_unsupported_schema_version'
)
subject
end
end end
context 'and the report is invalid' do context 'and the report is invalid' do
...@@ -211,13 +249,29 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do ...@@ -211,13 +249,29 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
} }
end end
let(:expected_errors) do context 'if enforce_security_report_validation is enabled' do
[ before do
'root is missing required keys: vulnerabilities' stub_feature_flags(enforce_security_report_validation: project)
] end
let(:expected_errors) do
[
'root is missing required keys: vulnerabilities'
]
end
it { is_expected.to match_array(expected_errors) }
end end
it { is_expected.to match_array(expected_errors) } context 'if enforce_security_report_validation is disabled' do
before do
stub_feature_flags(enforce_security_report_validation: false)
end
let(:expected_errors) { [] }
it { is_expected.to match_array(expected_errors) }
end
end end
end end
...@@ -355,6 +409,83 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do ...@@ -355,6 +409,83 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
end end
end end
describe '#deprecation_warnings' do
subject { validator.deprecation_warnings }
context 'when given a supported schema version' do
let(:report_type) { :dast }
let(:report_version) { described_class::SUPPORTED_VERSIONS[report_type].last }
let(:expected_deprecation_warnings) { [] }
context 'and the report is valid' do
let(:report_data) do
{
'version' => report_version,
'vulnerabilities' => []
}
end
it { is_expected.to match_array(expected_deprecation_warnings) }
end
context 'and the report is invalid' do
let(:report_data) do
{
'version' => report_version
}
end
it { is_expected.to match_array(expected_deprecation_warnings) }
end
end
context 'when given a deprecated schema version' do
let(:report_type) { :dast }
let(:report_version) { described_class::DEPRECATED_VERSIONS[report_type].last }
let(:expected_deprecation_warnings) do
[
"Version V2.7.0 for report type dast has been deprecated, supported versions for this report type are: 14.0.0, 14.0.1, 14.0.2, 14.0.3, 14.0.4, 14.0.5, 14.0.6, 14.1.0"
]
end
context 'and the report passes schema validation' do
let(:report_data) do
{
'version' => report_version,
'vulnerabilities' => []
}
end
it { is_expected.to match_array(expected_deprecation_warnings) }
end
context 'and the report does not pass schema validation' do
let(:report_data) do
{
'version' => 'V2.7.0'
}
end
it { is_expected.to match_array(expected_deprecation_warnings) }
end
end
context 'when given an unsupported schema version' do
let(:report_type) { :dast }
let(:report_version) { "21.37.0" }
let(:expected_deprecation_warnings) { [] }
let(:report_data) do
{
'version' => report_version,
'vulnerabilities' => []
}
end
it { is_expected.to match_array(expected_deprecation_warnings) }
end
end
describe '#warnings' do describe '#warnings' do
subject { validator.warnings } subject { validator.warnings }
...@@ -382,9 +513,29 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do ...@@ -382,9 +513,29 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
} }
end end
let(:expected_warnings) { [] } context 'if enforce_security_report_validation is enabled' do
before do
stub_feature_flags(enforce_security_report_validation: project)
end
it { is_expected.to match_array(expected_warnings) } let(:expected_warnings) { [] }
it { is_expected.to match_array(expected_warnings) }
end
context 'if enforce_security_report_validation is disabled' do
before do
stub_feature_flags(enforce_security_report_validation: false)
end
let(:expected_warnings) do
[
'root is missing required keys: vulnerabilities'
]
end
it { is_expected.to match_array(expected_warnings) }
end
end end
end end
...@@ -399,32 +550,24 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do ...@@ -399,32 +550,24 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
} }
end end
let(:expected_warnings) do let(:expected_warnings) { [] }
[
"Version V2.7.0 for report type dast has been deprecated, supported versions for this report type are: 14.0.0, 14.0.1, 14.0.2, 14.0.3, 14.0.4, 14.0.5, 14.0.6, 14.1.0"
]
end
it { is_expected.to match_array(expected_warnings) } it { is_expected.to match_array(expected_warnings) }
end end
context 'and the report does not pass schema validation' do context 'and the report does not pass schema validation' do
let(:report_data) do
{
'version' => 'V2.7.0'
}
end
context 'and enforce_security_report_validation is enabled' do context 'and enforce_security_report_validation is enabled' do
before do before do
stub_feature_flags(enforce_security_report_validation: true) stub_feature_flags(enforce_security_report_validation: true)
end end
let(:report_data) do let(:expected_warnings) { [] }
{
'version' => 'V2.7.0'
}
end
let(:expected_warnings) do
[
"Version V2.7.0 for report type dast has been deprecated, supported versions for this report type are: 14.0.0, 14.0.1, 14.0.2, 14.0.3, 14.0.4, 14.0.5, 14.0.6, 14.1.0"
]
end
it { is_expected.to match_array(expected_warnings) } it { is_expected.to match_array(expected_warnings) }
end end
...@@ -434,15 +577,8 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do ...@@ -434,15 +577,8 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
stub_feature_flags(enforce_security_report_validation: false) stub_feature_flags(enforce_security_report_validation: false)
end end
let(:report_data) do
{
'version' => 'V2.7.0'
}
end
let(:expected_warnings) do let(:expected_warnings) do
[ [
"Version V2.7.0 for report type dast has been deprecated, supported versions for this report type are: 14.0.0, 14.0.1, 14.0.2, 14.0.3, 14.0.4, 14.0.5, 14.0.6, 14.1.0",
"property '/version' does not match pattern: ^[0-9]+\\.[0-9]+\\.[0-9]+$", "property '/version' does not match pattern: ^[0-9]+\\.[0-9]+\\.[0-9]+$",
"root is missing required keys: vulnerabilities" "root is missing required keys: vulnerabilities"
] ]
......
...@@ -184,6 +184,22 @@ RSpec.describe Gitlab::Ci::Reports::Security::Report do ...@@ -184,6 +184,22 @@ RSpec.describe Gitlab::Ci::Reports::Security::Report do
end end
end end
describe 'warnings?' do
subject { report.warnings? }
context 'when the report does not have any errors' do
it { is_expected.to be_falsey }
end
context 'when the report has warnings' do
before do
report.add_warning('foo', 'bar')
end
it { is_expected.to be_truthy }
end
end
describe '#primary_scanner_order_to' do describe '#primary_scanner_order_to' do
let(:scanner_1) { build(:ci_reports_security_scanner) } let(:scanner_1) { build(:ci_reports_security_scanner) }
let(:scanner_2) { build(:ci_reports_security_scanner) } let(:scanner_2) { build(:ci_reports_security_scanner) }
......
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