summaryrefslogtreecommitdiff
path: root/ee/lib
diff options
context:
space:
mode:
authorAvielle Wolfe <awolfe@gitlab.com>2019-08-07 09:05:33 +0000
committerThong Kuah <tkuah@gitlab.com>2019-08-07 09:05:33 +0000
commitee036ce038711e8940af362633e8f183c7dc9db2 (patch)
treee83944f9612d6c61dad850fa94231920c7f8d3f8 /ee/lib
parent39f71ce5bca17ce6a7aab12761d2cb013e332d26 (diff)
downloadgitlab-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')
-rw-r--r--ee/lib/gitlab/ci/parsers/security/container_scanning.rb102
-rw-r--r--ee/lib/gitlab/ci/parsers/security/formatters/container_scanning.rb55
-rw-r--r--ee/lib/gitlab/ci/parsers/security/formatters/formatted_container_scanning_vulnerability.rb98
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