diff options
Diffstat (limited to 'lib/gitlab/ci/reports/security')
-rw-r--r-- | lib/gitlab/ci/reports/security/analyzer.rb | 20 | ||||
-rw-r--r-- | lib/gitlab/ci/reports/security/concerns/fingerprint_path_from_file.rb | 19 | ||||
-rw-r--r-- | lib/gitlab/ci/reports/security/identifier.rb | 69 | ||||
-rw-r--r-- | lib/gitlab/ci/reports/security/link.rb | 25 | ||||
-rw-r--r-- | lib/gitlab/ci/reports/security/scan.rb | 29 | ||||
-rw-r--r-- | lib/gitlab/ci/reports/security/scanned_resource.rb | 25 | ||||
-rw-r--r-- | lib/gitlab/ci/reports/security/scanner.rb | 60 |
7 files changed, 247 insertions, 0 deletions
diff --git a/lib/gitlab/ci/reports/security/analyzer.rb b/lib/gitlab/ci/reports/security/analyzer.rb new file mode 100644 index 00000000000..b88eaf87cef --- /dev/null +++ b/lib/gitlab/ci/reports/security/analyzer.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module Gitlab + module Ci + module Reports + module Security + class Analyzer + attr_reader :id, :name, :version, :vendor + + def initialize(id:, name:, version:, vendor:) + @id = id + @name = name + @version = version + @vendor = vendor + end + end + end + end + end +end diff --git a/lib/gitlab/ci/reports/security/concerns/fingerprint_path_from_file.rb b/lib/gitlab/ci/reports/security/concerns/fingerprint_path_from_file.rb new file mode 100644 index 00000000000..ec1d80e11c8 --- /dev/null +++ b/lib/gitlab/ci/reports/security/concerns/fingerprint_path_from_file.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Gitlab + module Ci + module Reports + module Security + module Concerns + module FingerprintPathFromFile + extend ActiveSupport::Concern + + def fingerprint_path + File.basename(file_path.to_s) + end + end + end + end + end + end +end diff --git a/lib/gitlab/ci/reports/security/identifier.rb b/lib/gitlab/ci/reports/security/identifier.rb new file mode 100644 index 00000000000..4ba943cdcbc --- /dev/null +++ b/lib/gitlab/ci/reports/security/identifier.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +module Gitlab + module Ci + module Reports + module Security + class Identifier + attr_reader :external_id + attr_reader :external_type + attr_reader :fingerprint + attr_reader :name + attr_reader :url + + def initialize(external_id:, external_type:, name:, url: nil) + @external_id = external_id + @external_type = external_type + @name = name + @url = url + + @fingerprint = generate_fingerprint + end + + def key + fingerprint + end + + def to_hash + %i[ + external_id + external_type + fingerprint + name + url + ].each_with_object({}) do |key, hash| + hash[key] = public_send(key) # rubocop:disable GitlabSecurity/PublicSend + end + end + + def ==(other) + other.external_type == external_type && + other.external_id == external_id + end + + def type_identifier? + cwe? || wasc? + end + + def cve? + external_type.to_s.casecmp?('cve') + end + + def cwe? + external_type.to_s.casecmp?('cwe') + end + + def wasc? + external_type.to_s.casecmp?('wasc') + end + + private + + def generate_fingerprint + Digest::SHA1.hexdigest("#{external_type}:#{external_id}") + end + end + end + end + end +end diff --git a/lib/gitlab/ci/reports/security/link.rb b/lib/gitlab/ci/reports/security/link.rb new file mode 100644 index 00000000000..1c4c05cd9ac --- /dev/null +++ b/lib/gitlab/ci/reports/security/link.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Gitlab + module Ci + module Reports + module Security + class Link + attr_accessor :name, :url + + def initialize(name: nil, url: nil) + @name = name + @url = url + end + + def to_hash + { + name: name, + url: url + }.compact + end + end + end + end + end +end diff --git a/lib/gitlab/ci/reports/security/scan.rb b/lib/gitlab/ci/reports/security/scan.rb new file mode 100644 index 00000000000..7dd0acc868b --- /dev/null +++ b/lib/gitlab/ci/reports/security/scan.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +module Gitlab + module Ci + module Reports + module Security + class Scan + attr_accessor :type, :status, :start_time, :end_time + + def initialize(params = {}) + @type = params.dig('type') + @status = params.dig('status') + @start_time = params.dig('start_time') + @end_time = params.dig('end_time') + end + + def to_hash + { + type: type, + status: status, + start_time: start_time, + end_time: end_time + }.compact + end + end + end + end + end +end diff --git a/lib/gitlab/ci/reports/security/scanned_resource.rb b/lib/gitlab/ci/reports/security/scanned_resource.rb new file mode 100644 index 00000000000..605577eafcd --- /dev/null +++ b/lib/gitlab/ci/reports/security/scanned_resource.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Gitlab + module Ci + module Reports + module Security + class ScannedResource + include Gitlab::Utils::StrongMemoize + + attr_reader :request_method + attr_reader :request_uri + + delegate :scheme, :host, :port, :path, :query, to: :request_uri, prefix: :url + + def initialize(uri, request_method) + raise ArgumentError unless uri.is_a?(URI) + + @request_method = request_method + @request_uri = uri + end + end + end + end + end +end diff --git a/lib/gitlab/ci/reports/security/scanner.rb b/lib/gitlab/ci/reports/security/scanner.rb new file mode 100644 index 00000000000..c1de03cea44 --- /dev/null +++ b/lib/gitlab/ci/reports/security/scanner.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +module Gitlab + module Ci + module Reports + module Security + class Scanner + ANALYZER_ORDER = { + "bundler_audit" => 1, + "retire.js" => 2, + "gemnasium" => 3, + "gemnasium-maven" => 3, + "gemnasium-python" => 3, + "bandit" => 1, + "semgrep" => 2 + }.freeze + + attr_accessor :external_id, :name, :vendor, :version + + alias_method :key, :external_id + + def initialize(external_id:, name:, vendor:, version:) + @external_id = external_id + @name = name + @vendor = vendor + @version = version + end + + def to_hash + { + external_id: external_id.to_s, + name: name.to_s, + vendor: vendor.presence + }.compact + end + + def ==(other) + other.external_id == external_id + end + + def <=>(other) + sort_keys.compact <=> other.sort_keys.compact + end + + protected + + def sort_keys + @sort_keys ||= [order, external_id, name, vendor] + end + + private + + def order + ANALYZER_ORDER.fetch(external_id, Float::INFINITY) + end + end + end + end + end +end |