summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab/ci/parsers/security
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/gitlab/ci/parsers/security')
-rw-r--r--spec/lib/gitlab/ci/parsers/security/common_spec.rb236
-rw-r--r--spec/lib/gitlab/ci/parsers/security/validators/schema_validator_spec.rb662
2 files changed, 747 insertions, 151 deletions
diff --git a/spec/lib/gitlab/ci/parsers/security/common_spec.rb b/spec/lib/gitlab/ci/parsers/security/common_spec.rb
index 1e96c717a4f..dfc5dec1481 100644
--- a/spec/lib/gitlab/ci/parsers/security/common_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/security/common_spec.rb
@@ -4,6 +4,18 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::Parsers::Security::Common do
describe '#parse!' do
+ let_it_be(:scanner_data) do
+ {
+ scan: {
+ scanner: {
+ id: "gemnasium",
+ name: "Gemnasium",
+ version: "2.1.0"
+ }
+ }
+ }
+ end
+
where(vulnerability_finding_signatures_enabled: [true, false])
with_them do
let_it_be(:pipeline) { create(:ci_pipeline) }
@@ -30,7 +42,9 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
describe 'schema validation' do
let(:validator_class) { Gitlab::Ci::Parsers::Security::Validators::SchemaValidator }
- let(:parser) { described_class.new('{}', report, vulnerability_finding_signatures_enabled, validate: validate) }
+ let(:data) { {}.merge(scanner_data) }
+ let(:json_data) { data.to_json }
+ let(:parser) { described_class.new(json_data, report, vulnerability_finding_signatures_enabled, validate: validate) }
subject(:parse_report) { parser.parse! }
@@ -38,172 +52,138 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Common do
allow(validator_class).to receive(:new).and_call_original
end
- context 'when show_report_validation_warnings is enabled' do
- before do
- stub_feature_flags(show_report_validation_warnings: true)
- end
-
- context 'when the validate flag is set to `false`' do
- let(:validate) { false }
- let(:valid?) { false }
- let(:errors) { ['foo'] }
-
- before do
- allow_next_instance_of(validator_class) do |instance|
- allow(instance).to receive(:valid?).and_return(valid?)
- allow(instance).to receive(:errors).and_return(errors)
- end
-
- allow(parser).to receive_messages(create_scanner: true, create_scan: true)
- end
-
- it 'instantiates the validator with correct params' do
- parse_report
-
- expect(validator_class).to have_received(:new).with(report.type, {}, report.version)
- end
-
- context 'when the report data is not valid according to the schema' do
- it 'adds warnings to the report' do
- expect { parse_report }.to change { report.warnings }.from([]).to([{ message: 'foo', type: 'Schema' }])
- end
-
- it 'keeps the execution flow as normal' do
- parse_report
+ context 'when the validate flag is set to `false`' do
+ let(:validate) { false }
+ let(:valid?) { false }
+ let(:errors) { ['foo'] }
+ let(:warnings) { ['bar'] }
- expect(parser).to have_received(:create_scanner)
- expect(parser).to have_received(:create_scan)
- end
+ before do
+ allow_next_instance_of(validator_class) do |instance|
+ allow(instance).to receive(:valid?).and_return(valid?)
+ allow(instance).to receive(:errors).and_return(errors)
+ allow(instance).to receive(:warnings).and_return(warnings)
end
- context 'when the report data is valid according to the schema' do
- let(:valid?) { true }
- let(:errors) { [] }
-
- it 'does not add warnings to the report' do
- expect { parse_report }.not_to change { report.errors }
- end
-
- it 'keeps the execution flow as normal' do
- parse_report
-
- expect(parser).to have_received(:create_scanner)
- expect(parser).to have_received(:create_scan)
- end
- end
+ allow(parser).to receive_messages(create_scanner: true, create_scan: true)
end
- context 'when the validate flag is set to `true`' do
- let(:validate) { true }
- let(:valid?) { false }
- let(:errors) { ['foo'] }
+ it 'instantiates the validator with correct params' do
+ parse_report
- before do
- allow_next_instance_of(validator_class) do |instance|
- allow(instance).to receive(:valid?).and_return(valid?)
- allow(instance).to receive(:errors).and_return(errors)
- end
+ expect(validator_class).to have_received(:new).with(
+ report.type,
+ data.deep_stringify_keys,
+ report.version,
+ project: pipeline.project,
+ scanner: data.dig(:scan, :scanner).deep_stringify_keys
+ )
+ end
- allow(parser).to receive_messages(create_scanner: true, create_scan: true)
+ context 'when the report data is not valid according to the schema' do
+ it 'adds warnings to the report' do
+ expect { parse_report }.to change { report.warnings }.from([]).to(
+ [
+ { message: 'foo', type: 'Schema' },
+ { message: 'bar', type: 'Schema' }
+ ]
+ )
end
- it 'instantiates the validator with correct params' do
+ it 'keeps the execution flow as normal' do
parse_report
- expect(validator_class).to have_received(:new).with(report.type, {}, report.version)
+ expect(parser).to have_received(:create_scanner)
+ expect(parser).to have_received(:create_scan)
end
+ end
- context 'when the report data is not valid according to the schema' do
- it 'adds errors to the report' do
- expect { parse_report }.to change { report.errors }.from([]).to([{ message: 'foo', type: 'Schema' }])
- end
-
- it 'does not try to create report entities' do
- parse_report
+ context 'when the report data is valid according to the schema' do
+ let(:valid?) { true }
+ let(:errors) { [] }
+ let(:warnings) { [] }
- expect(parser).not_to have_received(:create_scanner)
- expect(parser).not_to have_received(:create_scan)
- end
+ it 'does not add errors to the report' do
+ expect { parse_report }.not_to change { report.errors }
end
- context 'when the report data is valid according to the schema' do
- let(:valid?) { true }
- let(:errors) { [] }
-
- it 'does not add errors to the report' do
- expect { parse_report }.not_to change { report.errors }.from([])
- 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
- parse_report
+ it 'keeps the execution flow as normal' do
+ parse_report
- expect(parser).to have_received(:create_scanner)
- expect(parser).to have_received(:create_scan)
- end
+ expect(parser).to have_received(:create_scanner)
+ expect(parser).to have_received(:create_scan)
end
end
end
- context 'when show_report_validation_warnings is disabled' do
- before do
- stub_feature_flags(show_report_validation_warnings: false)
- end
-
- context 'when the validate flag is set as `false`' do
- let(:validate) { false }
+ context 'when the validate flag is set to `true`' do
+ let(:validate) { true }
+ let(:valid?) { false }
+ let(:errors) { ['foo'] }
+ let(:warnings) { ['bar'] }
- it 'does not run the validation logic' do
- parse_report
-
- expect(validator_class).not_to have_received(:new)
+ before do
+ allow_next_instance_of(validator_class) do |instance|
+ allow(instance).to receive(:valid?).and_return(valid?)
+ allow(instance).to receive(:errors).and_return(errors)
+ allow(instance).to receive(:warnings).and_return(warnings)
end
+
+ allow(parser).to receive_messages(create_scanner: true, create_scan: true)
end
- context 'when the validate flag is set as `true`' do
- let(:validate) { true }
- let(:valid?) { false }
+ it 'instantiates the validator with correct params' do
+ parse_report
- before do
- allow_next_instance_of(validator_class) do |instance|
- allow(instance).to receive(:valid?).and_return(valid?)
- allow(instance).to receive(:errors).and_return(['foo'])
- end
+ expect(validator_class).to have_received(:new).with(
+ report.type,
+ data.deep_stringify_keys,
+ report.version,
+ project: pipeline.project,
+ scanner: data.dig(:scan, :scanner).deep_stringify_keys
+ )
+ end
- allow(parser).to receive_messages(create_scanner: true, create_scan: true)
+ context 'when the report data is not valid according to the schema' do
+ it 'adds errors to the report' do
+ expect { parse_report }.to change { report.errors }.from([]).to(
+ [
+ { message: 'foo', type: 'Schema' },
+ { message: 'bar', type: 'Schema' }
+ ]
+ )
end
- it 'instantiates the validator with correct params' do
+ it 'does not try to create report entities' do
parse_report
- expect(validator_class).to have_received(:new).with(report.type, {}, report.version)
+ expect(parser).not_to have_received(:create_scanner)
+ expect(parser).not_to have_received(:create_scan)
end
+ end
- context 'when the report data is not valid according to the schema' do
- it 'adds errors to the report' do
- expect { parse_report }.to change { report.errors }.from([]).to([{ message: 'foo', type: 'Schema' }])
- end
-
- it 'does not try to create report entities' do
- parse_report
+ context 'when the report data is valid according to the schema' do
+ let(:valid?) { true }
+ let(:errors) { [] }
+ let(:warnings) { [] }
- expect(parser).not_to have_received(:create_scanner)
- expect(parser).not_to have_received(:create_scan)
- end
+ it 'does not add errors to the report' do
+ expect { parse_report }.not_to change { report.errors }.from([])
end
- context 'when the report data is valid according to the schema' do
- let(:valid?) { true }
-
- it 'does not add errors to the report' do
- expect { parse_report }.not_to change { report.errors }.from([])
- 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
- parse_report
+ it 'keeps the execution flow as normal' do
+ parse_report
- expect(parser).to have_received(:create_scanner)
- expect(parser).to have_received(:create_scan)
- end
+ expect(parser).to have_received(:create_scanner)
+ expect(parser).to have_received(:create_scan)
end
end
end
diff --git a/spec/lib/gitlab/ci/parsers/security/validators/schema_validator_spec.rb b/spec/lib/gitlab/ci/parsers/security/validators/schema_validator_spec.rb
index c83427b68ef..f6409c8b01f 100644
--- a/spec/lib/gitlab/ci/parsers/security/validators/schema_validator_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/security/validators/schema_validator_spec.rb
@@ -3,6 +3,18 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
+ let_it_be(:project) { create(:project) }
+
+ let(:scanner) do
+ {
+ 'id' => 'gemnasium',
+ 'name' => 'Gemnasium',
+ 'version' => '2.1.0'
+ }
+ end
+
+ let(:validator) { described_class.new(report_type, report_data, report_version, project: project, scanner: scanner) }
+
describe 'SUPPORTED_VERSIONS' do
schema_path = Rails.root.join("lib", "gitlab", "ci", "parsers", "security", "validators", "schemas")
@@ -47,48 +59,652 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Validators::SchemaValidator do
end
end
- using RSpec::Parameterized::TableSyntax
+ describe '#valid?' do
+ subject { validator.valid? }
- where(:report_type, :report_version, :expected_errors, :valid_data) do
- 'sast' | '10.0.0' | ['root is missing required keys: vulnerabilities'] | { 'version' => '10.0.0', 'vulnerabilities' => [] }
- :sast | '10.0.0' | ['root is missing required keys: vulnerabilities'] | { 'version' => '10.0.0', 'vulnerabilities' => [] }
- :secret_detection | '10.0.0' | ['root is missing required keys: vulnerabilities'] | { 'version' => '10.0.0', 'vulnerabilities' => [] }
- end
+ context 'when given a supported schema version' do
+ let(:report_type) { :dast }
+ let(:report_version) { described_class::SUPPORTED_VERSIONS[report_type].last }
- with_them do
- let(:validator) { described_class.new(report_type, report_data, report_version) }
+ context 'and the report is valid' do
+ let(:report_data) do
+ {
+ 'version' => report_version,
+ 'vulnerabilities' => []
+ }
+ end
- describe '#valid?' do
- subject { validator.valid? }
+ it { is_expected.to be_truthy }
+ end
- context 'when given data is invalid according to the schema' do
- let(:report_data) { {} }
+ context 'and the report is invalid' do
+ let(:report_data) do
+ {
+ 'version' => report_version
+ }
+ end
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',
+ security_report_scanner_id: 'gemnasium',
+ security_report_scanner_version: '2.1.0'
+ )
+
+ subject
+ end
end
+ end
+
+ context 'when given a deprecated schema version' do
+ let(:report_type) { :dast }
+ let(:report_version) { described_class::DEPRECATED_VERSIONS[report_type].last }
- context 'when given data is valid according to the schema' do
- let(:report_data) { valid_data }
+ context 'and the report passes schema validation' do
+ let(:report_data) do
+ {
+ 'version' => '10.0.0',
+ 'vulnerabilities' => []
+ }
+ end
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',
+ security_report_scanner_id: 'gemnasium',
+ security_report_scanner_version: '2.1.0'
+ )
+
+ subject
+ end
end
- context 'when no report_version is provided' do
- let(:report_version) { nil }
- let(:report_data) { valid_data }
+ context 'and the report does not pass schema validation' do
+ context 'and enforce_security_report_validation is enabled' do
+ before do
+ stub_feature_flags(enforce_security_report_validation: true)
+ end
+
+ let(:report_data) do
+ {
+ 'version' => 'V2.7.0'
+ }
+ end
- it 'does not fail' do
- expect { subject }.not_to raise_error
+ it { is_expected.to be_falsey }
+ end
+
+ context 'and enforce_security_report_validation is disabled' do
+ before do
+ stub_feature_flags(enforce_security_report_validation: false)
+ end
+
+ let(:report_data) do
+ {
+ 'version' => 'V2.7.0'
+ }
+ end
+
+ it { is_expected.to be_truthy }
end
end
end
- describe '#errors' do
- let(:report_data) { { 'version' => '10.0.0' } }
+ context 'when given an unsupported schema version' do
+ let(:report_type) { :dast }
+ let(:report_version) { "12.37.0" }
+
+ context 'if enforce_security_report_validation is enabled' do
+ before do
+ stub_feature_flags(enforce_security_report_validation: true)
+ end
+
+ context 'and the report is valid' do
+ let(:report_data) do
+ {
+ 'version' => report_version,
+ 'vulnerabilities' => []
+ }
+ end
+
+ 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',
+ security_report_scanner_id: 'gemnasium',
+ security_report_scanner_version: '2.1.0'
+ )
+
+ subject
+ end
+ end
+
+ context 'and the report is invalid' do
+ let(:report_data) do
+ {
+ 'version' => report_version
+ }
+ end
+
+ context 'and scanner information is empty' do
+ let(:scanner) { {} }
+
+ 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',
+ security_report_scanner_id: nil,
+ security_report_scanner_version: nil
+ )
+
+ 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',
+ security_report_scanner_id: nil,
+ security_report_scanner_version: nil
+ )
+
+ subject
+ end
+ end
+
+ it { is_expected.to be_falsey }
+ end
+ end
+
+ context 'if enforce_security_report_validation is disabled' do
+ before do
+ stub_feature_flags(enforce_security_report_validation: false)
+ end
+
+ context 'and the report is valid' do
+ let(:report_data) do
+ {
+ 'version' => report_version,
+ 'vulnerabilities' => []
+ }
+ end
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'and the report is invalid' do
+ let(:report_data) do
+ {
+ 'version' => report_version
+ }
+ end
+
+ it { is_expected.to be_truthy }
+ end
+ end
+ end
+ end
- subject { validator.errors }
+ describe '#errors' do
+ subject { validator.errors }
- it { is_expected.to eq(expected_errors) }
+ context 'when given a supported schema version' do
+ let(:report_type) { :dast }
+ let(:report_version) { described_class::SUPPORTED_VERSIONS[report_type].last }
+
+ context 'and the report is valid' do
+ let(:report_data) do
+ {
+ 'version' => report_version,
+ 'vulnerabilities' => []
+ }
+ end
+
+ let(:expected_errors) { [] }
+
+ it { is_expected.to match_array(expected_errors) }
+ end
+
+ context 'and the report is invalid' do
+ let(:report_data) do
+ {
+ 'version' => report_version
+ }
+ end
+
+ context 'if enforce_security_report_validation is enabled' do
+ before do
+ 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
+
+ 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
+
+ context 'when given a deprecated schema version' do
+ let(:report_type) { :dast }
+ let(:report_version) { described_class::DEPRECATED_VERSIONS[report_type].last }
+
+ context 'and the report passes schema validation' do
+ let(:report_data) do
+ {
+ 'version' => '10.0.0',
+ 'vulnerabilities' => []
+ }
+ end
+
+ let(:expected_errors) { [] }
+
+ it { is_expected.to match_array(expected_errors) }
+ end
+
+ context 'and the report does not pass schema validation' do
+ context 'and enforce_security_report_validation is enabled' do
+ before do
+ stub_feature_flags(enforce_security_report_validation: true)
+ end
+
+ let(:report_data) do
+ {
+ 'version' => 'V2.7.0'
+ }
+ end
+
+ let(:expected_errors) do
+ [
+ "property '/version' does not match pattern: ^[0-9]+\\.[0-9]+\\.[0-9]+$",
+ "root is missing required keys: vulnerabilities"
+ ]
+ end
+
+ it { is_expected.to match_array(expected_errors) }
+ end
+
+ context 'and enforce_security_report_validation is disabled' do
+ before do
+ stub_feature_flags(enforce_security_report_validation: false)
+ end
+
+ let(:report_data) do
+ {
+ 'version' => 'V2.7.0'
+ }
+ end
+
+ let(:expected_errors) { [] }
+
+ it { is_expected.to match_array(expected_errors) }
+ end
+ end
+ end
+
+ context 'when given an unsupported schema version' do
+ let(:report_type) { :dast }
+ let(:report_version) { "12.37.0" }
+
+ context 'if enforce_security_report_validation is enabled' do
+ before do
+ stub_feature_flags(enforce_security_report_validation: true)
+ end
+
+ context 'and the report is valid' do
+ let(:report_data) do
+ {
+ 'version' => report_version,
+ 'vulnerabilities' => []
+ }
+ end
+
+ let(:expected_errors) do
+ [
+ "Version 12.37.0 for report type dast is unsupported, 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, 14.1.1"
+ ]
+ end
+
+ it { is_expected.to match_array(expected_errors) }
+ end
+
+ context 'and the report is invalid' do
+ let(:report_data) do
+ {
+ 'version' => report_version
+ }
+ end
+
+ let(:expected_errors) do
+ [
+ "Version 12.37.0 for report type dast is unsupported, 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, 14.1.1",
+ "root is missing required keys: vulnerabilities"
+ ]
+ end
+
+ it { is_expected.to match_array(expected_errors) }
+ end
+ end
+
+ context 'if enforce_security_report_validation is disabled' do
+ before do
+ stub_feature_flags(enforce_security_report_validation: false)
+ end
+
+ context 'and the report is valid' do
+ let(:report_data) do
+ {
+ 'version' => report_version,
+ 'vulnerabilities' => []
+ }
+ end
+
+ let(:expected_errors) { [] }
+
+ it { is_expected.to match_array(expected_errors) }
+ end
+
+ context 'and the report is invalid' do
+ let(:report_data) do
+ {
+ 'version' => report_version
+ }
+ end
+
+ let(:expected_errors) { [] }
+
+ it { is_expected.to match_array(expected_errors) }
+ 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, 14.1.1"
+ ]
+ 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
+ subject { validator.warnings }
+
+ context 'when given a supported schema version' do
+ let(:report_type) { :dast }
+ let(:report_version) { described_class::SUPPORTED_VERSIONS[report_type].last }
+
+ context 'and the report is valid' do
+ let(:report_data) do
+ {
+ 'version' => report_version,
+ 'vulnerabilities' => []
+ }
+ end
+
+ let(:expected_warnings) { [] }
+
+ it { is_expected.to match_array(expected_warnings) }
+ end
+
+ context 'and the report is invalid' do
+ let(:report_data) do
+ {
+ 'version' => report_version
+ }
+ end
+
+ context 'if enforce_security_report_validation is enabled' do
+ before do
+ stub_feature_flags(enforce_security_report_validation: project)
+ end
+
+ 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
+
+ context 'when given a deprecated schema version' do
+ let(:report_type) { :dast }
+ let(:report_version) { described_class::DEPRECATED_VERSIONS[report_type].last }
+
+ context 'and the report passes schema validation' do
+ let(:report_data) do
+ {
+ 'vulnerabilities' => []
+ }
+ end
+
+ let(:expected_warnings) { [] }
+
+ it { is_expected.to match_array(expected_warnings) }
+ end
+
+ 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
+ before do
+ stub_feature_flags(enforce_security_report_validation: true)
+ end
+
+ let(:expected_warnings) { [] }
+
+ it { is_expected.to match_array(expected_warnings) }
+ end
+
+ context 'and enforce_security_report_validation is disabled' do
+ before do
+ stub_feature_flags(enforce_security_report_validation: false)
+ end
+
+ let(:expected_warnings) do
+ [
+ "property '/version' does not match pattern: ^[0-9]+\\.[0-9]+\\.[0-9]+$",
+ "root is missing required keys: vulnerabilities"
+ ]
+ end
+
+ it { is_expected.to match_array(expected_warnings) }
+ end
+ end
+ end
+
+ context 'when given an unsupported schema version' do
+ let(:report_type) { :dast }
+ let(:report_version) { "12.37.0" }
+
+ context 'if enforce_security_report_validation is enabled' do
+ before do
+ stub_feature_flags(enforce_security_report_validation: true)
+ end
+
+ context 'and the report is valid' do
+ let(:report_data) do
+ {
+ 'version' => report_version,
+ 'vulnerabilities' => []
+ }
+ end
+
+ let(:expected_warnings) { [] }
+
+ it { is_expected.to match_array(expected_warnings) }
+ end
+
+ context 'and the report is invalid' do
+ let(:report_data) do
+ {
+ 'version' => report_version
+ }
+ end
+
+ let(:expected_warnings) { [] }
+
+ it { is_expected.to match_array(expected_warnings) }
+ end
+ end
+
+ context 'if enforce_security_report_validation is disabled' do
+ before do
+ stub_feature_flags(enforce_security_report_validation: false)
+ end
+
+ context 'and the report is valid' do
+ let(:report_data) do
+ {
+ 'version' => report_version,
+ 'vulnerabilities' => []
+ }
+ end
+
+ let(:expected_warnings) do
+ [
+ "Version 12.37.0 for report type dast is unsupported, 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, 14.1.1"
+ ]
+ end
+
+ it { is_expected.to match_array(expected_warnings) }
+ end
+
+ context 'and the report is invalid' do
+ let(:report_data) do
+ {
+ 'version' => report_version
+ }
+ end
+
+ let(:expected_warnings) do
+ [
+ "Version 12.37.0 for report type dast is unsupported, 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, 14.1.1",
+ "root is missing required keys: vulnerabilities"
+ ]
+ end
+
+ it { is_expected.to match_array(expected_warnings) }
+ end
+ end
end
end
end