Merge pull request #17981 from Homebrew/sbom-schema-offline

Vendor SBOM schema
This commit is contained in:
Bo Anderson 2024-08-07 18:16:45 +01:00 committed by GitHub
commit 0bf3d74209
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 7822 additions and 52 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1240,8 +1240,6 @@ on_request: installed_on_request?, options:)
def fetch
return if previously_fetched_formula
SBOM.fetch_schema! if Homebrew::EnvConfig.developer?
fetch_dependencies
return if only_deps?

View File

@ -10,9 +10,7 @@ require "utils/curl"
# Rather than calling `new` directly, use one of the class methods like {SBOM.create}.
class SBOM
FILENAME = "sbom.spdx.json"
SCHEMA_URL = "https://spdx.github.io/spdx-3-model/model.jsonld"
SCHEMA_FILENAME = "sbom.spdx.schema.3.json"
SCHEMA_CACHE_TARGET = (HOMEBREW_CACHE/"sbom/#{SCHEMA_FILENAME}").freeze
SCHEMA_FILE = (HOMEBREW_LIBRARY_PATH/"data/schemas/sbom.spdx.schema.3.json").freeze
# Instantiates a {SBOM} for a new installation of a formula.
sig { params(formula: Formula, tab: Tab).returns(T.attached_class) }
@ -89,43 +87,9 @@ class SBOM
spdxfile(formula).exist?
end
sig { returns(T::Hash[String, String]) }
def self.fetch_schema!
return @schema if @schema.present?
url = SCHEMA_URL
target = SCHEMA_CACHE_TARGET
quieter = target.exist? && !target.empty?
curl_args = Utils::Curl.curl_args(retries: 0)
curl_args += ["--silent", "--time-cond", target.to_s] if quieter
begin
unless quieter
oh1 "Fetching SBOM schema"
ohai "Downloading #{url}"
end
Utils::Curl.curl_download(*curl_args, url, to: target, retries: 0)
FileUtils.touch(target, mtime: Time.now)
rescue ErrorDuringExecution
target.unlink if target.exist? && target.empty?
if target.exist?
opoo "SBOM schema update failed, falling back to cached version."
else
opoo "Failed to fetch SBOM schema, cannot perform SBOM validation!"
return {}
end
end
@schema = begin
JSON.parse(target.read, freeze: true)
rescue JSON::ParserError
target.unlink
opoo "Failed to fetch SBOM schema, cached version corrupted, cannot perform SBOM validation!"
{}
end
sig { returns(T::Hash[String, T.untyped]) }
def self.schema
@schema ||= JSON.parse(SCHEMA_FILE.read, freeze: true)
end
sig { params(bottling: T::Boolean).returns(T::Boolean) }
@ -136,14 +100,7 @@ class SBOM
return true
end
schema = SBOM.fetch_schema!
if schema.blank?
error_message = "Could not fetch JSON schema to validate SBOM!"
ENV["HOMEBREW_ENFORCE_SBOM"] ? odie(error_message) : opoo(error_message)
return false
end
schemer = JSONSchemer.schema(schema)
schemer = JSONSchemer.schema(SBOM.schema)
data = to_spdx_sbom(bottling:)
return true if schemer.valid?(data)

View File

@ -443,7 +443,6 @@ RSpec.describe FormulaInstaller do
it "shows audit problems if HOMEBREW_DEVELOPER is set" do
ENV["HOMEBREW_DEVELOPER"] = "1"
expect(SBOM).to receive(:fetch_schema!).and_return({})
formula_installer.fetch
formula_installer.install
expect(formula_installer).to receive(:audit_installed).and_call_original

View File

@ -2,7 +2,7 @@
require "sbom"
RSpec.describe SBOM, :needs_network do
RSpec.describe SBOM do
describe "#valid?" do
it "returns true if a minimal SBOM is valid" do
f = formula { url "foo-1.0" }