sbom 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitmodules +7 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/README.md +153 -0
- data/Rakefile +8 -0
- data/exe/sbom +346 -0
- data/lib/sbom/cyclonedx/generator.rb +307 -0
- data/lib/sbom/cyclonedx/parser.rb +275 -0
- data/lib/sbom/data/document.rb +143 -0
- data/lib/sbom/data/file.rb +169 -0
- data/lib/sbom/data/package.rb +417 -0
- data/lib/sbom/data/relationship.rb +43 -0
- data/lib/sbom/data/sbom.rb +124 -0
- data/lib/sbom/error.rb +13 -0
- data/lib/sbom/generator.rb +79 -0
- data/lib/sbom/license/data/spdx_licenses.json +8533 -0
- data/lib/sbom/license/scanner.rb +101 -0
- data/lib/sbom/output.rb +88 -0
- data/lib/sbom/parser.rb +111 -0
- data/lib/sbom/spdx/generator.rb +337 -0
- data/lib/sbom/spdx/parser.rb +426 -0
- data/lib/sbom/validation_result.rb +30 -0
- data/lib/sbom/validator.rb +261 -0
- data/lib/sbom/version.rb +5 -0
- data/lib/sbom.rb +54 -0
- data/sig/sbom.rbs +4 -0
- metadata +114 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sbom
|
|
4
|
+
module Data
|
|
5
|
+
class Relationship
|
|
6
|
+
attr_accessor :source, :target, :relationship_type,
|
|
7
|
+
:source_id, :target_id,
|
|
8
|
+
:source_type, :target_type
|
|
9
|
+
|
|
10
|
+
def initialize(source: nil, target: nil, relationship_type: nil)
|
|
11
|
+
@source = source
|
|
12
|
+
@target = target
|
|
13
|
+
@relationship_type = relationship_type&.strip
|
|
14
|
+
@source_id = nil
|
|
15
|
+
@target_id = nil
|
|
16
|
+
@source_type = nil
|
|
17
|
+
@target_type = nil
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def reset!
|
|
21
|
+
@source = nil
|
|
22
|
+
@target = nil
|
|
23
|
+
@relationship_type = nil
|
|
24
|
+
@source_id = nil
|
|
25
|
+
@target_id = nil
|
|
26
|
+
@source_type = nil
|
|
27
|
+
@target_type = nil
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def to_h
|
|
31
|
+
{
|
|
32
|
+
source: @source,
|
|
33
|
+
target: @target,
|
|
34
|
+
type: @relationship_type,
|
|
35
|
+
source_id: @source_id,
|
|
36
|
+
target_id: @target_id,
|
|
37
|
+
source_type: @source_type,
|
|
38
|
+
target_type: @target_type
|
|
39
|
+
}.compact
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sbom
|
|
4
|
+
module Data
|
|
5
|
+
class Sbom
|
|
6
|
+
attr_accessor :sbom_type, :version, :uuid, :bom_version
|
|
7
|
+
|
|
8
|
+
def initialize(sbom_type: :auto)
|
|
9
|
+
@sbom_type = sbom_type
|
|
10
|
+
@document = nil
|
|
11
|
+
@files = {}
|
|
12
|
+
@packages = {}
|
|
13
|
+
@relationships = []
|
|
14
|
+
@licenses = []
|
|
15
|
+
@annotations = []
|
|
16
|
+
@properties = []
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def document
|
|
20
|
+
@document
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def document=(doc)
|
|
24
|
+
@document = doc.is_a?(Hash) ? doc : doc&.to_h
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def add_document(doc)
|
|
28
|
+
@document = doc.is_a?(Hash) ? doc : doc&.to_h
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def files
|
|
32
|
+
@files.values
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def add_file(file)
|
|
36
|
+
data = file.is_a?(Hash) ? file : file.to_h
|
|
37
|
+
key = data[:name]
|
|
38
|
+
@files[key] = data if key
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def add_files(files_hash)
|
|
42
|
+
@files.merge!(files_hash) if files_hash.is_a?(Hash) && files_hash.any?
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def packages
|
|
46
|
+
@packages.values
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def add_package(package)
|
|
50
|
+
data = package.is_a?(Hash) ? package : package.to_h
|
|
51
|
+
key = [data[:name], data[:version]]
|
|
52
|
+
@packages[key] = data if data[:name]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def add_packages(packages_hash)
|
|
56
|
+
@packages.merge!(packages_hash) if packages_hash.is_a?(Hash) && packages_hash.any?
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def relationships
|
|
60
|
+
@relationships
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def add_relationship(relationship)
|
|
64
|
+
data = relationship.is_a?(Hash) ? relationship : relationship.to_h
|
|
65
|
+
@relationships << data
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def add_relationships(relationships_list)
|
|
69
|
+
@relationships.concat(relationships_list) if relationships_list.is_a?(Array)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def licenses
|
|
73
|
+
@licenses
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def add_license(license)
|
|
77
|
+
@licenses << license
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def add_licenses(licenses_list)
|
|
81
|
+
@licenses.concat(licenses_list) if licenses_list.is_a?(Array)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def annotations
|
|
85
|
+
@annotations
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def add_annotation(annotation)
|
|
89
|
+
@annotations << annotation
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def add_annotations(annotations_list)
|
|
93
|
+
@annotations.concat(annotations_list) if annotations_list.is_a?(Array)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def add_property(name, value)
|
|
97
|
+
@properties << [name.strip, value]
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def properties
|
|
101
|
+
@properties
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def to_h
|
|
105
|
+
result = {
|
|
106
|
+
type: @sbom_type,
|
|
107
|
+
version: @version,
|
|
108
|
+
uuid: @uuid,
|
|
109
|
+
bom_version: @bom_version
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
result[:document] = @document if @document
|
|
113
|
+
result[:files] = @files if @files.any?
|
|
114
|
+
result[:packages] = @packages if @packages.any?
|
|
115
|
+
result[:relationships] = @relationships if @relationships.any?
|
|
116
|
+
result[:licenses] = @licenses if @licenses.any?
|
|
117
|
+
result[:annotations] = @annotations if @annotations.any?
|
|
118
|
+
result[:properties] = @properties if @properties.any?
|
|
119
|
+
|
|
120
|
+
result.compact
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
data/lib/sbom/error.rb
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sbom
|
|
4
|
+
class Generator
|
|
5
|
+
VALID_FORMATS = %i[tag json yaml].freeze
|
|
6
|
+
VALID_TYPES = %i[spdx cyclonedx].freeze
|
|
7
|
+
|
|
8
|
+
def initialize(sbom_type: :spdx, format: :json, application: "sbom", version: Sbom::VERSION)
|
|
9
|
+
@sbom_type = validate_type(sbom_type)
|
|
10
|
+
@format = validate_format(format, @sbom_type)
|
|
11
|
+
@application = application
|
|
12
|
+
@version = version
|
|
13
|
+
@generator = create_generator
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def generate(project_name, sbom_data)
|
|
17
|
+
@generator.generate(project_name, sbom_data)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def output
|
|
21
|
+
@generator.output
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def to_h
|
|
25
|
+
@generator.to_h
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def sbom_type
|
|
29
|
+
@sbom_type
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def format
|
|
33
|
+
@format
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.generate(project_name, sbom_data, sbom_type: :spdx, format: :json)
|
|
37
|
+
gen = new(sbom_type: sbom_type, format: format)
|
|
38
|
+
gen.generate(project_name, sbom_data)
|
|
39
|
+
gen
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def validate_type(type)
|
|
45
|
+
type_sym = type.to_s.downcase.to_sym
|
|
46
|
+
return type_sym if VALID_TYPES.include?(type_sym)
|
|
47
|
+
|
|
48
|
+
:spdx
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def validate_format(format, sbom_type)
|
|
52
|
+
format_sym = format.to_s.downcase.to_sym
|
|
53
|
+
|
|
54
|
+
if sbom_type == :cyclonedx
|
|
55
|
+
return :json
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
return format_sym if VALID_FORMATS.include?(format_sym)
|
|
59
|
+
|
|
60
|
+
:json
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def create_generator
|
|
64
|
+
if @sbom_type == :cyclonedx
|
|
65
|
+
Cyclonedx::Generator.new(
|
|
66
|
+
format: @format,
|
|
67
|
+
application: @application,
|
|
68
|
+
version: @version
|
|
69
|
+
)
|
|
70
|
+
else
|
|
71
|
+
Spdx::Generator.new(
|
|
72
|
+
format: @format,
|
|
73
|
+
application: @application,
|
|
74
|
+
version: @version
|
|
75
|
+
)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|