Commit 0a718482 authored by Yevgeny Name's avatar Yevgeny Name

Add coverage fuzzing to security dashboard(backend)

This adds database support and graphql

Related MR https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36011
parent 497620d5
...@@ -12063,6 +12063,7 @@ The type of the security scanner. ...@@ -12063,6 +12063,7 @@ The type of the security scanner.
""" """
enum SecurityScannerType { enum SecurityScannerType {
CONTAINER_SCANNING CONTAINER_SCANNING
COVERAGE_FUZZING
DAST DAST
DEPENDENCY_SCANNING DEPENDENCY_SCANNING
SAST SAST
...@@ -14937,7 +14938,7 @@ enum VulnerabilityIssueLinkType { ...@@ -14937,7 +14938,7 @@ enum VulnerabilityIssueLinkType {
""" """
Represents a vulnerability location. The fields with data will depend on the vulnerability report type Represents a vulnerability location. The fields with data will depend on the vulnerability report type
""" """
union VulnerabilityLocation = VulnerabilityLocationContainerScanning | VulnerabilityLocationDast | VulnerabilityLocationDependencyScanning | VulnerabilityLocationSast | VulnerabilityLocationSecretDetection union VulnerabilityLocation = VulnerabilityLocationContainerScanning | VulnerabilityLocationCoverageFuzzing | VulnerabilityLocationDast | VulnerabilityLocationDependencyScanning | VulnerabilityLocationSast | VulnerabilityLocationSecretDetection
""" """
Represents the location of a vulnerability found by a container security scan Represents the location of a vulnerability found by a container security scan
...@@ -14959,6 +14960,36 @@ type VulnerabilityLocationContainerScanning { ...@@ -14959,6 +14960,36 @@ type VulnerabilityLocationContainerScanning {
operatingSystem: String operatingSystem: String
} }
"""
Represents the location of a vulnerability found by a Coverage Fuzzing scan
"""
type VulnerabilityLocationCoverageFuzzing {
"""
Number of the last relevant line in the vulnerable file
"""
endLine: String
"""
Path to the vulnerable file
"""
file: String
"""
Number of the first relevant line in the vulnerable file
"""
startLine: String
"""
Class containing the vulnerability
"""
vulnerableClass: String
"""
Method containing the vulnerability
"""
vulnerableMethod: String
}
""" """
Represents the location of a vulnerability found by a DAST scan Represents the location of a vulnerability found by a DAST scan
""" """
......
...@@ -35342,6 +35342,12 @@ ...@@ -35342,6 +35342,12 @@
"description": null, "description": null,
"isDeprecated": false, "isDeprecated": false,
"deprecationReason": null "deprecationReason": null
},
{
"name": "COVERAGE_FUZZING",
"description": null,
"isDeprecated": false,
"deprecationReason": null
} }
], ],
"possibleTypes": null "possibleTypes": null
...@@ -43978,6 +43984,11 @@ ...@@ -43978,6 +43984,11 @@
"name": "VulnerabilityLocationContainerScanning", "name": "VulnerabilityLocationContainerScanning",
"ofType": null "ofType": null
}, },
{
"kind": "OBJECT",
"name": "VulnerabilityLocationCoverageFuzzing",
"ofType": null
},
{ {
"kind": "OBJECT", "kind": "OBJECT",
"name": "VulnerabilityLocationDast", "name": "VulnerabilityLocationDast",
...@@ -44055,6 +44066,89 @@ ...@@ -44055,6 +44066,89 @@
"enumValues": null, "enumValues": null,
"possibleTypes": null "possibleTypes": null
}, },
{
"kind": "OBJECT",
"name": "VulnerabilityLocationCoverageFuzzing",
"description": "Represents the location of a vulnerability found by a Coverage Fuzzing scan",
"fields": [
{
"name": "endLine",
"description": "Number of the last relevant line in the vulnerable file",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "file",
"description": "Path to the vulnerable file",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "startLine",
"description": "Number of the first relevant line in the vulnerable file",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "vulnerableClass",
"description": "Class containing the vulnerability",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "vulnerableMethod",
"description": "Method containing the vulnerability",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{ {
"kind": "OBJECT", "kind": "OBJECT",
"name": "VulnerabilityLocationDast", "name": "VulnerabilityLocationDast",
...@@ -2246,6 +2246,18 @@ Represents the location of a vulnerability found by a container security scan ...@@ -2246,6 +2246,18 @@ Represents the location of a vulnerability found by a container security scan
| `image` | String | Name of the vulnerable container image | | `image` | String | Name of the vulnerable container image |
| `operatingSystem` | String | Operating system that runs on the vulnerable container image | | `operatingSystem` | String | Operating system that runs on the vulnerable container image |
## VulnerabilityLocationCoverageFuzzing
Represents the location of a vulnerability found by a Coverage Fuzzing scan
| Name | Type | Description |
| --- | ---- | ---------- |
| `endLine` | String | Number of the last relevant line in the vulnerable file |
| `file` | String | Path to the vulnerable file |
| `startLine` | String | Number of the first relevant line in the vulnerable file |
| `vulnerableClass` | String | Class containing the vulnerability |
| `vulnerableMethod` | String | Method containing the vulnerability |
## VulnerabilityLocationDast ## VulnerabilityLocationDast
Represents the location of a vulnerability found by a DAST scan Represents the location of a vulnerability found by a DAST scan
......
...@@ -15,7 +15,7 @@ module EE ...@@ -15,7 +15,7 @@ module EE
before_action :whitelist_query_limiting_ee_merge, only: [:merge] before_action :whitelist_query_limiting_ee_merge, only: [:merge]
before_action :authorize_read_pipeline!, only: [:container_scanning_reports, :dependency_scanning_reports, before_action :authorize_read_pipeline!, only: [:container_scanning_reports, :dependency_scanning_reports,
:license_scanning_reports, :license_scanning_reports,
:sast_reports, :secret_detection_reports, :dast_reports, :metrics_reports] :sast_reports, :secret_detection_reports, :dast_reports, :metrics_reports, :coverage_fuzzing_reports]
feature_category :container_scanning, only: [:container_scanning_reports] feature_category :container_scanning, only: [:container_scanning_reports]
feature_category :dependency_scanning, only: [:dependency_scanning_reports] feature_category :dependency_scanning, only: [:dependency_scanning_reports]
...@@ -54,6 +54,10 @@ module EE ...@@ -54,6 +54,10 @@ module EE
reports_response(merge_request.compare_metrics_reports) reports_response(merge_request.compare_metrics_reports)
end end
def coverage_fuzzing_reports
reports_response(merge_request.compare_coverage_fuzzing_reports(current_user))
end
private private
def whitelist_query_limiting_ee_merge def whitelist_query_limiting_ee_merge
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# Security::JobsFinder # Security::JobsFinder
# #
# Abstract class encapsulating common logic for finding jobs (builds) that are related to the Secure products # Abstract class encapsulating common logic for finding jobs (builds) that are related to the Secure products
# SAST, DAST, Dependency Scanning, Container Scanning and License Management # SAST, DAST, Dependency Scanning, Container Scanning and License Management, Coverage Fuzzing
# #
# Arguments: # Arguments:
# params: # params:
...@@ -15,7 +15,7 @@ module Security ...@@ -15,7 +15,7 @@ module Security
attr_reader :pipeline attr_reader :pipeline
def self.allowed_job_types def self.allowed_job_types
# Example return: [:sast, :dast, :dependency_scanning, :container_scanning, :license_management] # Example return: [:sast, :dast, :dependency_scanning, :container_scanning, :license_management, :coverage_fuzzing]
raise NotImplementedError, 'allowed_job_types must be overwritten to return an array of job types' raise NotImplementedError, 'allowed_job_types must be overwritten to return an array of job types'
end end
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
module Security module Security
class SecurityJobsFinder < JobsFinder class SecurityJobsFinder < JobsFinder
def self.allowed_job_types def self.allowed_job_types
[:sast, :dast, :dependency_scanning, :container_scanning, :secret_detection] [:sast, :dast, :dependency_scanning, :container_scanning, :secret_detection, :coverage_fuzzing]
end end
end end
end end
# frozen_string_literal: true
module Types
module VulnerabilityLocation
# rubocop: disable Graphql/AuthorizeTypes
class CoverageFuzzingType < BaseObject
graphql_name 'VulnerabilityLocationCoverageFuzzing'
description 'Represents the location of a vulnerability found by a Coverage Fuzzing scan'
field :vulnerable_class, GraphQL::STRING_TYPE, null: true,
description: 'Class containing the vulnerability',
hash_key: :class
field :end_line, GraphQL::STRING_TYPE, null: true,
description: 'Number of the last relevant line in the vulnerable file'
field :file, GraphQL::STRING_TYPE, null: true,
description: 'Path to the vulnerable file'
field :vulnerable_method, GraphQL::STRING_TYPE, null: true,
description: 'Method containing the vulnerability',
hash_key: :method
field :start_line, GraphQL::STRING_TYPE, null: true,
description: 'Number of the first relevant line in the vulnerable file'
end
end
end
...@@ -11,7 +11,8 @@ module Types ...@@ -11,7 +11,8 @@ module Types
VulnerabilityLocation::DependencyScanningType, VulnerabilityLocation::DependencyScanningType,
VulnerabilityLocation::DastType, VulnerabilityLocation::DastType,
VulnerabilityLocation::SastType, VulnerabilityLocation::SastType,
VulnerabilityLocation::SecretDetectionType VulnerabilityLocation::SecretDetectionType,
VulnerabilityLocation::CoverageFuzzingType
def self.resolve_type(object, context) def self.resolve_type(object, context)
case object[:report_type] case object[:report_type]
...@@ -25,6 +26,8 @@ module Types ...@@ -25,6 +26,8 @@ module Types
VulnerabilityLocation::SastType VulnerabilityLocation::SastType
when 'secret_detection' when 'secret_detection'
VulnerabilityLocation::SecretDetectionType VulnerabilityLocation::SecretDetectionType
when 'coverage_fuzzing'
VulnerabilityLocation::CoverageFuzzingType
else else
raise UnexpectedReportType, "Report type must be one of #{::Vulnerabilities::Occurrence::REPORT_TYPES.keys}" raise UnexpectedReportType, "Report type must be one of #{::Vulnerabilities::Occurrence::REPORT_TYPES.keys}"
end end
......
...@@ -58,7 +58,7 @@ module EE ...@@ -58,7 +58,7 @@ module EE
with_file_types(METRICS_REPORT_FILE_TYPES) with_file_types(METRICS_REPORT_FILE_TYPES)
end end
scope :coverage_fuzzing, -> do scope :coverage_fuzzing_reports, -> do
with_file_types(COVERAGE_FUZZING_REPORT_TYPES) with_file_types(COVERAGE_FUZZING_REPORT_TYPES)
end end
end end
......
...@@ -159,7 +159,8 @@ module EE ...@@ -159,7 +159,8 @@ module EE
container_scanning: report_type_enabled?(:container_scanning), container_scanning: report_type_enabled?(:container_scanning),
dast: report_type_enabled?(:dast), dast: report_type_enabled?(:dast),
dependency_scanning: report_type_enabled?(:dependency_scanning), dependency_scanning: report_type_enabled?(:dependency_scanning),
license_scanning: report_type_enabled?(:license_scanning) license_scanning: report_type_enabled?(:license_scanning),
coverage_fuzzing: report_type_enabled?(:coverage_fuzzing)
} }
end end
...@@ -233,6 +234,16 @@ module EE ...@@ -233,6 +234,16 @@ module EE
compare_reports(::Ci::CompareMetricsReportsService) compare_reports(::Ci::CompareMetricsReportsService)
end end
def has_coverage_fuzzing_reports?
!!actual_head_pipeline&.has_reports?(::Ci::JobArtifact.coverage_fuzzing_reports)
end
def compare_coverage_fuzzing_reports(current_user)
return missing_report_error("coverage fuzzing") unless has_coverage_fuzzing_reports?
compare_reports(::Ci::CompareSecurityReportsService, current_user, 'coverage_fuzzing')
end
def synchronize_approval_rules_from_target_project def synchronize_approval_rules_from_target_project
return if merged? return if merged?
......
...@@ -21,12 +21,7 @@ module EE ...@@ -21,12 +21,7 @@ module EE
def expose_security_dashboard? def expose_security_dashboard?
return false unless can?(current_user, :read_vulnerability, pipeline.project) return false unless can?(current_user, :read_vulnerability, pipeline.project)
batch_lookup_report_artifact_for_file_type(:sast) || Ci::JobArtifact::SECURITY_REPORT_FILE_TYPES.any? { |file_type| batch_lookup_report_artifact_for_file_type(file_type.to_sym) }
batch_lookup_report_artifact_for_file_type(:secret_detection) ||
batch_lookup_report_artifact_for_file_type(:dependency_scanning) ||
batch_lookup_report_artifact_for_file_type(:dast) ||
batch_lookup_report_artifact_for_file_type(:container_scanning) ||
batch_lookup_report_artifact_for_file_type(:coverage_fuzzing)
end end
def degradation_threshold(file_type) def degradation_threshold(file_type)
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
window.gl.mrWidgetData.dast_help_path = '#{help_page_path("user/application_security/dast/index")}'; window.gl.mrWidgetData.dast_help_path = '#{help_page_path("user/application_security/dast/index")}';
window.gl.mrWidgetData.dependency_scanning_help_path = '#{help_page_path("user/application_security/dependency_scanning/index")}'; window.gl.mrWidgetData.dependency_scanning_help_path = '#{help_page_path("user/application_security/dependency_scanning/index")}';
window.gl.mrWidgetData.secret_scanning_help_path = '#{help_page_path('user/application_security/sast/index', anchor: 'secret-detection')}'; window.gl.mrWidgetData.secret_scanning_help_path = '#{help_page_path('user/application_security/sast/index', anchor: 'secret-detection')}';
window.gl.mrWidgetData.coverage_fuzzinghelp_path = '#{help_page_path("user/application_security/coverage_fuzzing/index")}';
window.gl.mrWidgetData.vulnerability_feedback_help_path = '#{help_page_path("user/application_security/index")}'; window.gl.mrWidgetData.vulnerability_feedback_help_path = '#{help_page_path("user/application_security/index")}';
window.gl.mrWidgetData.visual_review_app_available = '#{@project.feature_available?(:visual_review_app)}' === 'true'; window.gl.mrWidgetData.visual_review_app_available = '#{@project.feature_available?(:visual_review_app)}' === 'true';
window.gl.mrWidgetData.license_scanning_comparison_path = '#{license_scanning_reports_project_merge_request_path(@project, @merge_request) if @project.feature_available?(:license_scanning)}' window.gl.mrWidgetData.license_scanning_comparison_path = '#{license_scanning_reports_project_merge_request_path(@project, @merge_request) if @project.feature_available?(:license_scanning)}'
......
---
title: Add coverage fuzzing to security dashboard(backend)
merge_request: 37173
author:
type: added
...@@ -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[codequality container_scanning dast dependency_scanning license_management license_scanning performance browser_performance load_performance sast secret_detection].each do |report_type| %i[codequality container_scanning dast dependency_scanning license_management 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
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
}, },
"category": { "category": {
"type": "string", "type": "string",
"enum": ["sast", "dependency_scanning", "container_scanning", "dast"] "enum": ["sast", "dependency_scanning", "container_scanning", "dast", "coverage_fuzzing"]
}, },
"project_fingerprint": { "type": "string" }, "project_fingerprint": { "type": "string" },
"branch": { "type": ["string", "null"] }, "branch": { "type": ["string", "null"] },
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
"auto_fix_container_scanning": true, "auto_fix_container_scanning": true,
"auto_fix_dast": true, "auto_fix_dast": true,
"auto_fix_dependency_scanning": false, "auto_fix_dependency_scanning": false,
"auto_fix_sast": false "auto_fix_sast": false,
"auto_fix_coverage_fuzzing": false
} }
} }
{"security_setting": {"auto_fix_container_scanning": true,"auto_fix_dast": true,"auto_fix_dependency_scanning": false,"auto_fix_sast": false}} {"security_setting": {"auto_fix_container_scanning": true,"auto_fix_dast": true,"auto_fix_dependency_scanning": false,"auto_fix_sast": false, "auto_fix_coverage": false}}
...@@ -18,7 +18,8 @@ RSpec.describe Resolvers::SecurityReportSummaryResolver do ...@@ -18,7 +18,8 @@ RSpec.describe Resolvers::SecurityReportSummaryResolver do
dast: [:scanned_resources_count, :vulnerabilities_count], dast: [:scanned_resources_count, :vulnerabilities_count],
sast: [:scanned_resources_count, :vulnerabilities_count], sast: [:scanned_resources_count, :vulnerabilities_count],
container_scanning: [:scanned_resources_count, :vulnerabilities_count], container_scanning: [:scanned_resources_count, :vulnerabilities_count],
dependency_scanning: [:scanned_resources_count, :vulnerabilities_count] dependency_scanning: [:scanned_resources_count, :vulnerabilities_count],
coverage_fuzzing: [:scanned_resources_count, :vulnerabilities_count]
} }
end end
......
...@@ -66,7 +66,8 @@ RSpec.describe Projects::Security::ConfigurationPresenter do ...@@ -66,7 +66,8 @@ RSpec.describe Projects::Security::ConfigurationPresenter do
security_scan(:container_scanning, configured: false), security_scan(:container_scanning, configured: false),
security_scan(:dependency_scanning, configured: false), security_scan(:dependency_scanning, configured: false),
security_scan(:license_scanning, configured: false), security_scan(:license_scanning, configured: false),
security_scan(:secret_detection, configured: true) security_scan(:secret_detection, configured: true),
security_scan(:coverage_fuzzing, configured: false)
) )
end end
end end
...@@ -87,7 +88,8 @@ RSpec.describe Projects::Security::ConfigurationPresenter do ...@@ -87,7 +88,8 @@ RSpec.describe Projects::Security::ConfigurationPresenter do
security_scan(:container_scanning, configured: false), security_scan(:container_scanning, configured: false),
security_scan(:dependency_scanning, configured: false), security_scan(:dependency_scanning, configured: false),
security_scan(:license_scanning, configured: false), security_scan(:license_scanning, configured: false),
security_scan(:secret_detection, configured: false) security_scan(:secret_detection, configured: false),
security_scan(:coverage_fuzzing, configured: false)
) )
end end
end end
...@@ -115,7 +117,8 @@ RSpec.describe Projects::Security::ConfigurationPresenter do ...@@ -115,7 +117,8 @@ RSpec.describe Projects::Security::ConfigurationPresenter do
security_scan(:container_scanning, configured: false), security_scan(:container_scanning, configured: false),
security_scan(:dependency_scanning, configured: false), security_scan(:dependency_scanning, configured: false),
security_scan(:license_scanning, configured: false), security_scan(:license_scanning, configured: false),
security_scan(:secret_detection, configured: true) security_scan(:secret_detection, configured: true),
security_scan(:coverage_fuzzing, configured: false)
) )
end end
...@@ -130,7 +133,8 @@ RSpec.describe Projects::Security::ConfigurationPresenter do ...@@ -130,7 +133,8 @@ RSpec.describe Projects::Security::ConfigurationPresenter do
security_scan(:container_scanning, configured: false), security_scan(:container_scanning, configured: false),
security_scan(:dependency_scanning, configured: false), security_scan(:dependency_scanning, configured: false),
security_scan(:license_scanning, configured: false), security_scan(:license_scanning, configured: false),
security_scan(:secret_detection, configured: false) security_scan(:secret_detection, configured: false),
security_scan(:coverage_fuzzing, configured: false)
) )
end end
...@@ -151,7 +155,8 @@ RSpec.describe Projects::Security::ConfigurationPresenter do ...@@ -151,7 +155,8 @@ RSpec.describe Projects::Security::ConfigurationPresenter do
security_scan(:container_scanning, configured: false), security_scan(:container_scanning, configured: false),
security_scan(:dependency_scanning, configured: false), security_scan(:dependency_scanning, configured: false),
security_scan(:license_scanning, configured: false), security_scan(:license_scanning, configured: false),
security_scan(:secret_detection, configured: false) security_scan(:secret_detection, configured: false),
security_scan(:coverage_fuzzing, configured: false)
) )
end end
...@@ -164,7 +169,8 @@ RSpec.describe Projects::Security::ConfigurationPresenter do ...@@ -164,7 +169,8 @@ RSpec.describe Projects::Security::ConfigurationPresenter do
security_scan(:container_scanning, configured: false), security_scan(:container_scanning, configured: false),
security_scan(:dependency_scanning, configured: false), security_scan(:dependency_scanning, configured: false),
security_scan(:license_scanning, configured: true), security_scan(:license_scanning, configured: true),
security_scan(:secret_detection, configured: true) security_scan(:secret_detection, configured: true),
security_scan(:coverage_fuzzing, configured: false)
) )
end end
......
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