Skip to content

Commit f095682

Browse files
add json format support
Signed-off-by: Jeffrey Zhang <[email protected]>
1 parent 36b5faa commit f095682

File tree

3 files changed

+74
-10
lines changed

3 files changed

+74
-10
lines changed

cyclonedx-ruby.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
88
spec.description = 'CycloneDX is a lightweight software bill-of-material (SBOM) specification designed for use in application security contexts and supply chain component analysis. This Gem generates CycloneDX BOMs from Ruby projects.'
99
spec.authors = ['Joseph Kobti', 'Steve Springett']
1010
spec.email = '[email protected]'
11-
spec.files = ['lib/bom_builder.rb', 'lib/bom_helpers.rb', 'lib/licenses.json']
11+
spec.files = ['lib/bom_builder.rb', 'lib/bom_helpers.rb', 'lib/licenses.json', 'lib/bom_component.rb']
1212
spec.homepage = 'https://github.com/CycloneDX/cyclonedx-ruby-gem'
1313
spec.license = 'Apache-2.0'
1414
spec.executables << 'cyclonedx-ruby'

lib/bom_component.rb

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
2+
class BomComponent
3+
DEFAULT_TYPE = "library".freeze
4+
HASH_ALG = 'SHA-256'.freeze
5+
6+
def initialize(gem)
7+
@name = gem['name']
8+
@version = gem['version']
9+
@description = gem['description']
10+
@hash = gem['hash']
11+
@purl = gem['purl']
12+
@gem = gem
13+
end
14+
15+
def hash_val
16+
component_hash = {
17+
"type": DEFAULT_TYPE,
18+
"name": @name,
19+
"version": @version,
20+
"description": @description,
21+
"purl": @purl,
22+
"hashes": [
23+
"alg": HASH_ALG,
24+
"content": @hash
25+
]
26+
}
27+
28+
if @gem['license_id']
29+
component_hash[:"licenses"] = [
30+
"license": {
31+
"id": @gem['license_id']
32+
}
33+
]
34+
elsif @gem['license_name']
35+
component_hash[:"licenses"] = [
36+
"license": {
37+
"name": @gem['license_name']
38+
}
39+
]
40+
end
41+
42+
[component_hash]
43+
44+
end
45+
end

lib/bom_helpers.rb

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
# Copyright (c) OWASP Foundation. All Rights Reserved.
2222
#
2323
# frozen_string_literal: true
24+
25+
require_relative 'bom_component'
26+
2427
def purl(name, version)
2528
"pkg:gem/#{name}@#{version}"
2629
end
@@ -30,6 +33,30 @@ def random_urn_uuid
3033
end
3134

3235
def build_bom(gems, format)
36+
if format == 'json'
37+
build_json_bom(gems)
38+
else
39+
build_bom_xml(gems)
40+
end
41+
end
42+
43+
def build_json_bom(gems)
44+
bom_hash = {
45+
"bomFormat": "CycloneDX",
46+
"specVersion": "1.1",
47+
"serialNumber": random_urn_uuid,
48+
"version": 1,
49+
"components": []
50+
}
51+
52+
gems.each do |gem|
53+
bom_hash[:components] += BomComponent.new(gem).hash_val()
54+
end
55+
56+
JSON.pretty_generate(bom_hash)
57+
end
58+
59+
def build_bom_xml(gems)
3360
builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
3461
attributes = { 'xmlns' => 'http://cyclonedx.org/schema/bom/1.1', 'version' => '1', 'serialNumber' => random_urn_uuid }
3562
xml.bom(attributes) do
@@ -62,15 +89,7 @@ def build_bom(gems, format)
6289
end
6390
end
6491

65-
xml = builder.to_xml
66-
67-
# Format verified to be either xml (default) or json in setup
68-
if format == 'json'
69-
JSON.pretty_generate(Hash.from_xml(xml))
70-
else
71-
xml
72-
end
73-
92+
builder.to_xml
7493
end
7594

7695
def get_gem(name, version)

0 commit comments

Comments
 (0)