Skip to content

Commit

Permalink
Update sbom.rb
Browse files Browse the repository at this point in the history
  • Loading branch information
SMillerDev committed May 3, 2024
1 parent 1360d16 commit 1b4e913
Showing 1 changed file with 119 additions and 112 deletions.
231 changes: 119 additions & 112 deletions Library/Homebrew/sbom.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,40 +25,40 @@ def self.create(formula, compiler: nil, stdlib: nil)
build = formula.build
runtime_deps = formula.runtime_dependencies(undeclared: false)
attributes = {
"name" => formula.name,
"homebrew_version" => HOMEBREW_VERSION,
"spdxfile" => formula.prefix/FILENAME,
"built_as_bottle" => build.bottle?,
"installed_as_dependency" => false,
"installed_on_request" => false,
"poured_from_bottle" => false,
"loaded_from_api" => false,
"time" => Time.now.to_i,
"source_modified_time" => formula.source_modified_time.to_i,
"compiler" => compiler,
"stdlib" => stdlib,
"aliases" => formula.aliases,
"runtime_dependencies" => SBOM.runtime_deps_hash(formula, runtime_deps),
"arch" => Hardware::CPU.arch,
"license" => SPDX.license_expression_to_string(formula.license),
"built_on" => DevelopmentTools.build_system_info,
"source" => {
"path" => formula.specified_path.to_s,
"tap" => formula.tap&.name,
"tap_git_head" => nil, # Filled in later if possible
"spec" => formula.active_spec_sym.to_s,
"patches" => formula.stable&.patches,
"bottle" => formula.bottle_hash,
"stable" => {
"version" => formula.stable&.version,
"url" => formula.stable&.url,
"checksum" => formula.stable&.checksum,
:name => formula.name,
:homebrew_version => HOMEBREW_VERSION,
:spdxfile => formula.prefix/FILENAME,
:built_as_bottle => build.bottle?,
:installed_as_dependency => false,
:installed_on_request => false,
:poured_from_bottle => false,
:loaded_from_api => false,
:time => Time.now.to_i,
:source_modified_time => formula.source_modified_time.to_i,
:compiler => compiler,
:stdlib => stdlib,
:aliases => formula.aliases,
:runtime_dependencies => SBOM.runtime_deps_hash(formula, runtime_deps),
:arch => Hardware::CPU.arch,
:license => SPDX.license_expression_to_string(formula.license),
:built_on => DevelopmentTools.build_system_info,
:source => {
:path => formula.specified_path.to_s,
:tap => formula.tap&.name,
:tap_git_head => nil, # Filled in later if possible
:spec => formula.active_spec_sym.to_s,
:patches => formula.stable&.patches,
:bottle => formula.bottle_hash,
:stable => {
:version => formula.stable&.version,
:url => formula.stable&.url,
:checksum => formula.stable&.checksum,
},
},
}

# We can only get `tap_git_head` if the tap is installed locally
attributes["source"]["tap_git_head"] = T.must(formula.tap).git_head if formula.tap&.installed?
attributes[:source][:tap_git_head] = T.must(formula.tap).git_head if formula.tap&.installed?

new(attributes)
end
Expand Down Expand Up @@ -108,37 +108,37 @@ def write
def generate_relations_json(runtime_dependency_declaration, compiler_declaration)
runtime = runtime_dependency_declaration.map do |dependency|
{
"spdxElementId" => dependency["SPDXID"],
"relationshipType" => "RUNTIME_DEPENDENCY_OF",
"relatedSpdxElement" => "SPDXRef-Bottle-#{name}",
:spdxElementId => dependency[:SPDXID],
:relationshipType => :RUNTIME_DEPENDENCY_OF,
:relatedSpdxElement => "SPDXRef-Bottle-#{name}",
}
end
patches = source["patches"].map do |_patch|
patches = source[:patches].map do |_patch|
{
"spdxElementId" => "SPDXRef-Patch-#{name}",
"relationshipType" => "PATCH_APPLIED",
"relatedSpdxElement" => "SPDXRef-Archive-#{name}-src",
:spdxElementId => "SPDXRef-Patch-#{name}",
:relationshipType => :PATCH_APPLIED,
:relatedSpdxElement => "SPDXRef-Archive-#{name}-src",
}
end

base = [
{
"spdxElementId" => "SPDXRef-File-#{name}",
"relationshipType" => "PACKAGE_OF",
"relatedSpdxElement" => "SPDXRef-Archive-#{name}-src",
:spdxElementId => "SPDXRef-File-#{name}",
:relationshipType => :PACKAGE_OF,
:relatedSpdxElement => "SPDXRef-Archive-#{name}-src",
},
{
"spdxElementId" => "SPDXRef-Compiler",
"relationshipType" => "BUILD_TOOL_OF",
"relatedSpdxElement" => "SPDXRef-Package-#{name}-src",
:spdxElementId => "SPDXRef-Compiler",
:relationshipType => :BUILD_TOOL_OF,
:relatedSpdxElement => "SPDXRef-Package-#{name}-src",
},
]

if compiler_declaration["SPDXRef-Stdlib"].present?
base += {
"spdxElementId" => "SPDXRef-Stdlib",
"relationshipType" => "DEPENDENCY_OF",
"relatedSpdxElement" => "SPDXRef-Bottle-#{name}",
:spdxElementId => "SPDXRef-Stdlib",
:relationshipType => :DEPENDENCY_OF,
:relatedSpdxElement => "SPDXRef-Bottle-#{name}",
}
end

Expand All @@ -150,26 +150,26 @@ def generate_packages_json(runtime_dependency_declaration, compiler_declaration)
bottle = []
if get_bottle_info(source["bottle"])
bottle << {
"SPDXID" => "SPDXRef-Bottle-#{name}",
"name" => name.to_s,
"versionInfo" => stable_version.to_s,
"filesAnalyzed" => false,
"licenseDeclared" => "NOASSERTION",
"builtDate" => source_modified_time.to_s,
"licenseConcluded" => license,
"downloadLocation" => T.must(get_bottle_info(source["bottle"]))["url"],
"copyrightText" => "NOASSERTION",
"externalRefs" => [
:SPDXID => "SPDXRef-Bottle-#{name}",
:name => name.to_s,
:versionInfo => stable_version.to_s,
:filesAnalyzed => false,
:licenseDeclared => assert_value(nil),
:builtDate => source_modified_time.to_s,
:licenseConcluded => license,
:downloadLocation => T.must(get_bottle_info(source["bottle"]))["url"],
:copyrightText => assert_value(nil),
:externalRefs => [
{
"referenceCategory" => "PACKAGE-MANAGER",
"referenceLocator" => "pkg:brew/#{tap}/#{name}@#{stable_version}",
"referenceType" => "purl",
:referenceCategory => "PACKAGE-MANAGER",
:referenceLocator => "pkg:brew/#{tap}/#{name}@#{stable_version}",
:referenceType => "purl",
},
],
"checksums" => [
:checksums => [
{
"algorithm" => "SHA256",
"checksumValue" => T.must(get_bottle_info(source["bottle"]))["sha256"],
:algorithm => "SHA256",
:checksumValue => T.must(get_bottle_info(source["bottle"]))["sha256"],
},
],
}
Expand All @@ -181,11 +181,11 @@ def generate_packages_json(runtime_dependency_declaration, compiler_declaration)
"name" => name.to_s,
"versionInfo" => stable_version.to_s,
"filesAnalyzed" => false,
"licenseDeclared" => "NOASSERTION",
"licenseDeclared" => assert_value(nil),
"builtDate" => source_modified_time.to_s,
"licenseConcluded" => license || "NOASSERTION",
"licenseConcluded" => assert_value(license),
"downloadLocation" => source["stable"]["url"],
"copyrightText" => "NOASSERTION",
"copyrightText" => assert_value(nil),
"externalRefs" => [],
"checksums" => [
{
Expand All @@ -209,14 +209,14 @@ def to_spdx_sbom
"name" => dependency["name"],
"versionInfo" => dependency["pkg_version"],
"filesAnalyzed" => false,
"licenseDeclared" => "NOASSERTION",
"licenseConcluded" => dependency["license"] || "NOASSERTION",
"downloadLocation" => bottle_info.present? ? bottle_info["url"] : "NOASSERTION",
"copyrightText" => "NOASSERTION",
"licenseDeclared" => assert_value(nil),
"licenseConcluded" => assert_value(dependency["license"]),
"downloadLocation" => assert_value(bottle_info.present? ? bottle_info["url"] : nil),
"copyrightText" => assert_value(nil),
"checksums" => [
{
"algorithm" => "SHA256",
"checksumValue" => bottle_info.present? ? bottle_info["sha256"] : "NOASSERTION",
"checksumValue" => assert_value(bottle_info.present? ? bottle_info["sha256"] : nil),
},
],
"externalRefs" => [
Expand All @@ -232,49 +232,49 @@ def to_spdx_sbom

compiler_info = {
"SPDXRef-Compiler" => {
"SPDXID" => "SPDXRef-Compiler",
"name" => compiler.to_s,
"versionInfo" => T.unsafe(built_on["xcode"]) || "NOASSERTION",
"filesAnalyzed" => false,
"licenseDeclared" => "NOASSERTION",
"licenseConcluded" => "NOASSERTION",
"copyrightText" => "NOASSERTION",
"downloadLocation" => "NOASSERTION",
"checksums" => [],
"externalRefs" => [],
:SPDXID => "SPDXRef-Compiler",
:name => compiler.to_s,
:versionInfo => assert_value(built_on["xcode"]),
:filesAnalyzed => false,
:licenseDeclared => assert_value(nil),
:licenseConcluded => assert_value(nil),
:copyrightText => assert_value(nil),
:downloadLocation => assert_value(nil),
:checksums => [],
:externalRefs => [],
},
}

if stdlib.present?
compiler_info["SPDXRef-Stdlib"] = {
"SPDXID" => "SPDXRef-Stdlib",
"name" => stdlib,
"versionInfo" => stdlib,
"filesAnalyzed" => false,
"licenseDeclared" => "NOASSERTION",
"licenseConcluded" => "NOASSERTION",
"copyrightText" => "NOASSERTION",
"downloadLocation" => "NOASSERTION",
"checksums" => [],
"externalRefs" => [],
:SPDXID => "SPDXRef-Stdlib",
:name => stdlib,
:versionInfo => stdlib,
:filesAnalyzed => false,
:licenseDeclared => assert_value(nil),
:licenseConcluded => assert_value(nil),
:copyrightText => assert_value(nil),
:downloadLocation => assert_value(nil),
:checksums => [],
:externalRefs => [],
}
end

packages = generate_packages_json(runtime_full, compiler_info)
{
"SPDXID" => "SPDXRef-DOCUMENT",
"spdxVersion" => "SPDX-2.3",
"name" => "SBOM-SPDX-#{name}-#{stable_version}",
"creationInfo" => {
"created" => DateTime.now.to_s,
"creators" => ["Tool: https://github.com/homebrew/brew@#{homebrew_version}"],
:SPDXID => "SPDXRef-DOCUMENT",
:spdxVersion => "SPDX-2.3",
:name => "SBOM-SPDX-#{name}-#{stable_version}",
:creationInfo => {
:created => DateTime.now.to_s,
:creators => ["Tool: https://github.com/homebrew/brew@#{homebrew_version}"],
},
"dataLicense" => "CC0-1.0",
"documentNamespace" => "https://formulae.brew.sh/spdx/#{name}-#{stable_version}.json",
"documentDescribes" => packages.map { |dependency| dependency["SPDXID"] },
"files" => [],
"packages" => packages,
"relationships" => generate_relations_json(runtime_full, compiler_info),
:dataLicense => "CC0-1.0",
:documentNamespace => "https://formulae.brew.sh/spdx/#{name}-#{stable_version}.json",
:documentDescribes => packages.map { |dependency| dependency["SPDXID"] },
:files => [],
:packages => packages,
:relationships => generate_relations_json(runtime_full, compiler_info),
}
end

Expand All @@ -283,14 +283,14 @@ def self.runtime_deps_hash(formula, deps)
deps.map do |dep|
f = dep.to_formula
{
"full_name" => f.full_name,
"name" => f.name,
"version" => f.version.to_s,
"revision" => f.revision,
"pkg_version" => f.pkg_version.to_s,
"declared_directly" => formula.deps.include?(dep),
"license" => SPDX.license_expression_to_string(f.license),
"bottle" => f.bottle_hash,
:full_name => f.full_name,
:name => f.name,
:version => f.version.to_s,
:revision => f.revision,
:pkg_version => f.pkg_version.to_s,
:declared_directly => formula.deps.include?(dep),
:license => SPDX.license_expression_to_string(f.license),
:bottle => f.bottle_hash,
}
end
end
Expand Down Expand Up @@ -333,22 +333,29 @@ def bottle?

sig { returns(T.nilable(Tap)) }
def tap
tap_name = source["tap"]
tap_name = source[:tap]
Tap.fetch(tap_name) if tap_name
end

sig { returns(Symbol) }
def spec
source["spec"].to_sym
source[:spec].to_sym
end

sig { returns(T.nilable(Version)) }
def stable_version
source["stable"]["version"]
source[:stable][:version]
end

sig { returns(Time) }
def source_modified_time
Time.at(@source_modified_time || 0)
end

sig { params(val: T.nilable(T.untyped)).returns(T.any(String,Symbol)) }
def assert_value(val)
return :NOASSERTION unless val.present?

val
end
end

0 comments on commit 1b4e913

Please sign in to comment.