diff options
author | Avielle Wolfe <awolfe@gitlab.com> | 2019-08-07 09:05:33 +0000 |
---|---|---|
committer | Thong Kuah <tkuah@gitlab.com> | 2019-08-07 09:05:33 +0000 |
commit | ee036ce038711e8940af362633e8f183c7dc9db2 (patch) | |
tree | e83944f9612d6c61dad850fa94231920c7f8d3f8 /ee/lib | |
parent | 39f71ce5bca17ce6a7aab12761d2cb013e332d26 (diff) | |
download | gitlab-ce-ee036ce038711e8940af362633e8f183c7dc9db2.tar.gz |
Extract container scanning formatters
* Extract Formatters::ContainerScanning
This class encapsulates the formatting logic for individual
vulnerabiltiies that was previously found in the container
scanning parser.
* Extract Formatters::FormattedContainerScanningVulnerability
This class represents a formatted container scanning
vulnerability.
Diffstat (limited to 'ee/lib')
3 files changed, 157 insertions, 98 deletions
diff --git a/ee/lib/gitlab/ci/parsers/security/container_scanning.rb b/ee/lib/gitlab/ci/parsers/security/container_scanning.rb index 500bfed79c4..37e5542e8ab 100644 --- a/ee/lib/gitlab/ci/parsers/security/container_scanning.rb +++ b/ee/lib/gitlab/ci/parsers/security/container_scanning.rb @@ -27,108 +27,14 @@ module Gitlab def format_report(data) vulnerabilities = data['vulnerabilities'] unapproved = data['unapproved'] - results = [] + formatter = Formatters::ContainerScanning.new(data['image']) - vulnerabilities.each do |vulnerability| + vulnerabilities.map do |vulnerability| # We only report unapproved vulnerabilities next unless unapproved.include?(vulnerability['vulnerability']) - results.append(format_vulnerability(vulnerability, data['image'])) - end - - results - end - - def format_vulnerability(vulnerability, image) - { - 'category' => 'container_scanning', - 'message' => message(vulnerability), - 'description' => description(vulnerability), - 'cve' => vulnerability['vulnerability'], - 'severity' => translate_severity(vulnerability['severity']), - 'solution' => solution(vulnerability), - 'confidence' => 'Medium', - 'location' => { - 'image' => image, - 'operating_system' => vulnerability["namespace"], - 'dependency' => { - 'package' => { - 'name' => vulnerability["featurename"] - }, - 'version' => vulnerability["featureversion"] - } - }, - 'scanner' => { 'id' => 'clair', 'name' => 'Clair' }, - 'identifiers' => [ - { - 'type' => 'cve', - 'name' => vulnerability['vulnerability'], - 'value' => vulnerability['vulnerability'], - 'url' => vulnerability['link'] - } - ], - 'links' => [{ 'url' => vulnerability['link'] }] - } - end - - def translate_severity(severity) - case severity - when 'Negligible' - 'low' - when 'Unknown', 'Low', 'Medium', 'High', 'Critical' - severity.downcase - when 'Defcon1' - 'critical' - else - safe_severity = ERB::Util.html_escape(severity) - raise SecurityReportParserError, "Unknown severity in container scanning report: #{safe_severity}" - end - end - - def message(vulnerability) - format( - vulnerability, - %w[vulnerability featurename] => - '%{vulnerability} in %{featurename}', - 'vulnerability' => - '%{vulnerability}' - ) - end - - def description(vulnerability) - format( - vulnerability, - 'description' => - '%{description}', - %w[featurename featureversion] => - '%{featurename}:%{featureversion} is affected by %{vulnerability}', - 'featurename' => - '%{featurename} is affected by %{vulnerability}', - 'namespace' => - '%{namespace} is affected by %{vulnerability}' - ) - end - - def solution(vulnerability) - format( - vulnerability, - %w[fixedby featurename featureversion] => - 'Upgrade %{featurename} from %{featureversion} to %{fixedby}', - %w[fixedby featurename] => - 'Upgrade %{featurename} to %{fixedby}', - 'fixedby' => - 'Upgrade to %{fixedby}' - ) - end - - def format(vulnerability, definitions) - definitions.each do |keys, value| - if vulnerability.values_at(*Array(keys)).all?(&:present?) - return value % vulnerability.symbolize_keys - end - end - - nil + formatter.format(vulnerability) + end.compact end def create_location(location_data) diff --git a/ee/lib/gitlab/ci/parsers/security/formatters/container_scanning.rb b/ee/lib/gitlab/ci/parsers/security/formatters/container_scanning.rb new file mode 100644 index 00000000000..dde2ab96891 --- /dev/null +++ b/ee/lib/gitlab/ci/parsers/security/formatters/container_scanning.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +module Gitlab + module Ci + module Parsers + module Security + module Formatters + class ContainerScanning + def initialize(image) + @image = image + end + + def format(vulnerability) + formatted_vulnerability = FormattedContainerScanningVulnerability.new(vulnerability) + + { + 'category' => 'container_scanning', + 'message' => formatted_vulnerability.message, + 'description' => formatted_vulnerability.description, + 'cve' => formatted_vulnerability.cve, + 'severity' => formatted_vulnerability.severity, + 'solution' => formatted_vulnerability.solution, + 'confidence' => 'Medium', + 'location' => { + 'image' => image, + 'operating_system' => formatted_vulnerability.operating_system, + 'dependency' => { + 'package' => { + 'name' => formatted_vulnerability.package_name + }, + 'version' => formatted_vulnerability.version + } + }, + 'scanner' => { 'id' => 'clair', 'name' => 'Clair' }, + 'identifiers' => [ + { + 'type' => 'cve', + 'name' => formatted_vulnerability.cve, + 'value' => formatted_vulnerability.cve, + 'url' => formatted_vulnerability.url + } + ], + 'links' => [{ 'url' => formatted_vulnerability.url }] + } + end + + private + + attr_reader :image + end + end + end + end + end +end diff --git a/ee/lib/gitlab/ci/parsers/security/formatters/formatted_container_scanning_vulnerability.rb b/ee/lib/gitlab/ci/parsers/security/formatters/formatted_container_scanning_vulnerability.rb new file mode 100644 index 00000000000..cc4167e8dca --- /dev/null +++ b/ee/lib/gitlab/ci/parsers/security/formatters/formatted_container_scanning_vulnerability.rb @@ -0,0 +1,98 @@ +# frozen_string_literal: true + +module Gitlab + module Ci + module Parsers + module Security + module Formatters + class FormattedContainerScanningVulnerability + def initialize(vulnerability) + @vulnerability = vulnerability + end + + def message + @message ||= format_definitions( + %w[vulnerability featurename] => '%{vulnerability} in %{featurename}', + 'vulnerability' => '%{vulnerability}' + ) + end + + def description + @description ||= format_definitions( + 'description' => '%{description}', + %w[featurename featureversion] => '%{featurename}:%{featureversion} is affected by %{vulnerability}', + 'featurename' => '%{featurename} is affected by %{vulnerability}', + 'namespace' => '%{namespace} is affected by %{vulnerability}' + ) + end + + def severity + raw_severity = vulnerability['severity'] + + @severity ||= case raw_severity + when 'Negligible' + 'low' + when 'Unknown', 'Low', 'Medium', 'High', 'Critical' + raw_severity.downcase + when 'Defcon1' + 'critical' + else + safe_severity = ERB::Util.html_escape(raw_severity) + raise( + ::Gitlab::Ci::Parsers::Security::Common::SecurityReportParserError, + "Unknown severity in container scanning report: #{safe_severity}" + ) + end + end + + def solution + @solution ||= format_definitions( + %w[fixedby featurename featureversion] => 'Upgrade %{featurename} from %{featureversion} to %{fixedby}', + %w[fixedby featurename] => 'Upgrade %{featurename} to %{fixedby}', + 'fixedby' => 'Upgrade to %{fixedby}' + ) + end + + def cve + @cve ||= vulnerability['vulnerability'] + end + + def operating_system + @operating_system ||= vulnerability['namespace'] + end + + def package_name + @package_name ||= vulnerability['featurename'] + end + + def version + @version ||= vulnerability['featureversion'] + end + + def url + @url ||= vulnerability['link'] + end + + private + + attr_reader :vulnerability + + def format_definitions(definitions) + find_definitions(definitions).then do |_, value| + if value.present? + value % vulnerability.symbolize_keys + end + end + end + + def find_definitions(definitions) + definitions.find do |keys, value| + vulnerability.values_at(*keys).all?(&:present?) + end + end + end + end + end + end + end +end |