summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab/ci/parsers/security/validators/schema_validator_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/gitlab/ci/parsers/security/validators/schema_validator_spec.rb')
-rw-r--r--spec/lib/gitlab/ci/parsers/security/validators/schema_validator_spec.rb662
1 files changed, 639 insertions, 23 deletions
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