Commit 1e962cfc authored by Lin Jen-Shin's avatar Lin Jen-Shin

Merge branch '9397/split-severity-and-confidence-levels' into 'master'

Split Severity and Confidence values for vulnerability occurrences

Closes #9397

See merge request gitlab-org/gitlab-ee!9495
parents 0c80a079 4d9eb9d7
......@@ -39,8 +39,8 @@ class Gitlab::Seeder::Vulnerabilities
uuid: random_uuid,
name: 'Cipher with no integrity',
report_type: :sast,
severity: random_level,
confidence: random_level,
severity: random_severity_level,
confidence: random_confidence_level,
project_fingerprint: random_fingerprint,
location_fingerprint: random_fingerprint,
primary_identifier: primary_identifier,
......@@ -82,8 +82,12 @@ class Gitlab::Seeder::Vulnerabilities
project.issues.create!(author: author, title: title)
end
def random_level
::Vulnerabilities::Occurrence::LEVELS.keys.sample
def random_confidence_level
::Vulnerabilities::Occurrence::CONFIDENCE_LEVELS.keys.sample
end
def random_severity_level
::Vulnerabilities::Occurrence::SEVERITY_LEVELS.keys.sample
end
def metadata(line)
......
......@@ -49,7 +49,7 @@ module Security
return items unless params[:severity].present?
items.by_severities(
Vulnerabilities::Occurrence::LEVELS.values_at(
Vulnerabilities::Occurrence::SEVERITY_LEVELS.values_at(
*params[:severity]).compact)
end
......
......@@ -9,18 +9,6 @@ module Vulnerabilities
paginates_per 20
# Used for both severity and confidence
LEVELS = {
undefined: 0,
ignore: 1,
unknown: 2,
experimental: 3,
low: 4,
medium: 5,
high: 6,
critical: 7
}.with_indifferent_access.freeze
sha_attribute :project_fingerprint
sha_attribute :location_fingerprint
......@@ -33,6 +21,28 @@ module Vulnerabilities
has_many :occurrence_pipelines, class_name: 'Vulnerabilities::OccurrencePipeline'
has_many :pipelines, through: :occurrence_pipelines, class_name: 'Ci::Pipeline'
CONFIDENCE_LEVELS = {
undefined: 0,
ignore: 1,
unknown: 2,
experimental: 3,
low: 4,
medium: 5,
high: 6,
confirmed: 7
}.with_indifferent_access.freeze
SEVERITY_LEVELS = {
undefined: 0,
info: 1,
unknown: 2,
# experimental: 3, formerly used by confidence, no longer applicable
low: 4,
medium: 5,
high: 6,
critical: 7
}.with_indifferent_access.freeze
REPORT_TYPES = {
sast: 0,
dependency_scanning: 1,
......@@ -40,7 +50,9 @@ module Vulnerabilities
dast: 3
}.with_indifferent_access.freeze
enum confidence: CONFIDENCE_LEVELS, _prefix: :confidence
enum report_type: REPORT_TYPES
enum severity: SEVERITY_LEVELS, _prefix: :severity
validates :scanner, presence: true
validates :project, presence: true
......@@ -54,8 +66,8 @@ module Vulnerabilities
# validates :location_fingerprint, presence: true, uniqueness: { scope: [:primary_identifier_id, :scanner_id, :ref, :pipeline_id, :project_id] }
validates :name, presence: true
validates :report_type, presence: true
validates :severity, presence: true, inclusion: { in: LEVELS.keys }
validates :confidence, presence: true, inclusion: { in: LEVELS.keys }
validates :severity, presence: true
validates :confidence, presence: true
validates :metadata_version, presence: true
validates :raw_metadata, presence: true
......@@ -85,7 +97,9 @@ module Vulnerabilities
end
def self.counted_by_severity
group(:severity).count
group(:severity).count.each_with_object({}) do |(severity, count), accum|
accum[SEVERITY_LEVELS[severity]] = count
end
end
def feedback(feedback_type:)
......@@ -124,26 +138,6 @@ module Vulnerabilities
feedback(feedback_type: 'issue')
end
# Override getter and setter for :severity as we can't use enum (it conflicts with :confidence)
# To be replaced with enum using _prefix when migrating to rails 5
def severity
LEVELS.key(read_attribute(:severity))
end
def severity=(severity)
write_attribute(:severity, LEVELS[severity])
end
# Override getter and setter for :confidence as we can't use enum (it conflicts with :severity)
# To be replaced with enum using _prefix when migrating to rails 5
def confidence
LEVELS.key(read_attribute(:confidence))
end
def confidence=(confidence)
write_attribute(:confidence, LEVELS[confidence])
end
def metadata
strong_memoize(:metadata) do
begin
......
......@@ -3,7 +3,7 @@
class Vulnerabilities::HistoryEntity < Grape::Entity
present_collection true
Vulnerabilities::Occurrence::LEVELS.keys.each do |level|
Vulnerabilities::Occurrence::SEVERITY_LEVELS.keys.each do |level|
expose level do |object|
counts(by_severity[level]&.group_by(&:day) || {})
end
......
# frozen_string_literal: true
class VulnerabilitySummaryEntity < Grape::Entity
Vulnerabilities::Occurrence::LEVELS.each do |severity_name, severity|
Vulnerabilities::Occurrence::SEVERITY_LEVELS.each do |severity_name, severity|
expose severity_name do |param|
object[severity] || 0
end
......
---
title: Split severity and confidence values for vulnerabilities
merge_request: 9495
author:
type: changed
......@@ -90,7 +90,7 @@ module Gitlab
def severity(value)
case Integer(value)
when 0
'ignore'
'info'
when 1
'low'
when 2
......@@ -116,7 +116,7 @@ module Gitlab
when 3
'high'
when 4
'critical'
'confirmed'
else
'unknown'
end
......
......@@ -336,9 +336,8 @@ describe Groups::Security::VulnerabilitiesController do
expect(json_response).to be_an(Hash)
expect(json_response).to eq({
"undefined" => {},
"ignore" => {},
"info" => {},
"unknown" => {},
"experimental" => {},
"low" => {},
"medium" => {},
"high" => {},
......
......@@ -16,11 +16,11 @@
"vulnerability_feedback_dismissal_path": { "type": "string" },
"confidence" : {
"type": "string",
"enum": ["undefined", "ignore", "unknown", "experimental", "low", "medium", "high", "critical"]
"enum": ["undefined", "ignore", "unknown", "experimental", "low", "medium", "high", "confirmed"]
},
"severity" : {
"type": "string",
"enum": ["undefined", "ignore", "unknown", "experimental", "low", "medium", "high", "critical"]
"enum": ["undefined", "info", "unknown", "low", "medium", "high", "critical"]
},
"report_type": {
"type": "string",
......
......@@ -124,7 +124,7 @@ describe Gitlab::Ci::Parsers::Security::Dast do
using RSpec::Parameterized::TableSyntax
where(:severity, :expected) do
'0' | 'ignore'
'0' | 'info'
'1' | 'low'
'2' | 'medium'
'3' | 'high'
......@@ -147,7 +147,7 @@ describe Gitlab::Ci::Parsers::Security::Dast do
'1' | 'low'
'2' | 'medium'
'3' | 'high'
'4' | 'critical'
'4' | 'confirmed'
'42' | 'unknown'
'' | 'unknown'
end
......
......@@ -3,7 +3,9 @@
require 'spec_helper'
describe Vulnerabilities::Occurrence do
it { is_expected.to define_enum_for(:confidence) }
it { is_expected.to define_enum_for(:report_type) }
it { is_expected.to define_enum_for(:severity) }
describe 'associations' do
it { is_expected.to belong_to(:project) }
......@@ -29,9 +31,7 @@ describe Vulnerabilities::Occurrence do
it { is_expected.to validate_presence_of(:metadata_version) }
it { is_expected.to validate_presence_of(:raw_metadata) }
it { is_expected.to validate_presence_of(:severity) }
it { is_expected.to validate_inclusion_of(:severity).in_array(described_class::LEVELS.keys) }
it { is_expected.to validate_presence_of(:confidence) }
it { is_expected.to validate_inclusion_of(:confidence).in_array(described_class::LEVELS.keys) }
end
context 'database uniqueness' do
......@@ -219,7 +219,7 @@ describe Vulnerabilities::Occurrence do
end
end
describe '.count_by_severity' do
describe '.counted_by_severity' do
let!(:high_vulnerabilities) { create_list(:vulnerabilities_occurrence, 3, severity: :high) }
let!(:medium_vulnerabilities) { create_list(:vulnerabilities_occurrence, 2, severity: :medium) }
let!(:low_vulnerabilities) { create_list(:vulnerabilities_occurrence, 1, severity: :low) }
......
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