formula_installer: verify attestations at bottle fetch time

See discussion at #18544.
This commit is contained in:
Carlo Cabrera 2024-10-14 13:55:28 +08:00
parent d1e539cb84
commit aedbf7ac43
No known key found for this signature in database
GPG Key ID: C74D447FC549A1D0

View File

@ -1306,43 +1306,33 @@ on_request: installed_on_request?, options:)
oh1 "Fetching #{Formatter.identifier(formula.full_name)}".strip oh1 "Fetching #{Formatter.identifier(formula.full_name)}".strip
if pour_bottle?(output_warning: true) downloadable_object = downloadable
check_attestation = if pour_bottle?(output_warning: true)
fetch_bottle_tab fetch_bottle_tab
!downloadable_object.cached_download.exist?
else else
@formula = Homebrew::API::Formula.source_download(formula) if formula.loaded_from_api? @formula = Homebrew::API::Formula.source_download(formula) if formula.loaded_from_api?
formula.fetch_patches formula.fetch_patches
formula.resources.each(&:fetch) formula.resources.each(&:fetch)
false
end end
downloadable.fetch downloadable_object.fetch
self.class.fetched << formula
end
sig { returns(Downloadable) }
def downloadable
if (bottle_path = formula.local_bottle_path)
Resource::Local.new(bottle_path)
elsif pour_bottle?
T.must(formula.bottle)
else
T.must(formula.resource)
end
end
sig { void }
def pour
# We skip `gh` to avoid a bootstrapping cycle, in the off-chance a user attempts # We skip `gh` to avoid a bootstrapping cycle, in the off-chance a user attempts
# to explicitly `brew install gh` without already having a version for bootstrapping. # to explicitly `brew install gh` without already having a version for bootstrapping.
# We also skip bottle installs from local bottle paths, as these are done in CI # We also skip bottle installs from local bottle paths, as these are done in CI
# as part of the build lifecycle before attestations are produced. # as part of the build lifecycle before attestations are produced.
if Homebrew::Attestation.enabled? && if check_attestation &&
Homebrew::Attestation.enabled? &&
formula.tap&.core_tap? && formula.tap&.core_tap? &&
formula.name != "gh" && formula.name != "gh" &&
formula.local_bottle_path.blank? formula.local_bottle_path.blank?
ohai "Verifying attestation for #{formula.name}" ohai "Verifying attestation for #{formula.name}"
begin begin
Homebrew::Attestation.check_core_attestation T.must(formula.bottle) Homebrew::Attestation.check_core_attestation T.cast(downloadable_object, Bottle)
rescue Homebrew::Attestation::GhIncompatible rescue Homebrew::Attestation::GhIncompatible
# A small but significant number of users have developer mode enabled # A small but significant number of users have developer mode enabled
# but *also* haven't upgraded in a long time, meaning that their `gh` # but *also* haven't upgraded in a long time, meaning that their `gh`
@ -1399,6 +1389,28 @@ on_request: installed_on_request?, options:)
end end
end end
self.class.fetched << formula
rescue CannotInstallFormulaError
if (cached_download = downloadable_object&.cached_download)&.exist?
cached_download.unlink
end
raise
end
sig { returns(Downloadable) }
def downloadable
if (bottle_path = formula.local_bottle_path)
Resource::Local.new(bottle_path)
elsif pour_bottle?
T.must(formula.bottle)
else
T.must(formula.resource)
end
end
sig { void }
def pour
HOMEBREW_CELLAR.cd do HOMEBREW_CELLAR.cd do
downloadable.downloader.stage downloadable.downloader.stage
end end