1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
# frozen_string_literal: true
module Gitlab
module Ci
module Reports
module Sbom
class Component
include Gitlab::Utils::StrongMemoize
attr_reader :component_type, :version, :path
def initialize(type:, name:, purl:, version:)
@component_type = type
@name = name
@raw_purl = purl
@version = version
end
def <=>(other)
sort_by_attributes(self) <=> sort_by_attributes(other)
end
def ingestible?
supported_component_type? && supported_purl_type?
end
def purl
return unless @raw_purl
::Sbom::PackageUrl.parse(@raw_purl)
end
strong_memoize_attr :purl
def purl_type
purl.type
end
def type
component_type
end
def name
return @name unless purl
[purl.namespace, purl.name].compact.join('/')
end
def key
[name, version, purl&.type]
end
private
def supported_component_type?
::Enums::Sbom.component_types.include?(component_type.to_sym)
end
def supported_purl_type?
# the purl type is not required as per the spec: https://cyclonedx.org/docs/1.4/json/#components_items_purl
return true unless purl
# however, if the purl type is provided, it _must be valid_
::Enums::Sbom.purl_types.include?(purl.type.to_sym)
end
def sort_by_attributes(component)
[
component.name,
purl_type_int(component),
component_type_int(component),
component.version.to_s
]
end
def component_type_int(component)
::Enums::Sbom::COMPONENT_TYPES.fetch(component.component_type.to_sym)
end
def purl_type_int(component)
::Enums::Sbom::PURL_TYPES.fetch(component.purl&.type&.to_sym, 0)
end
end
end
end
end
end
|