attestations: improve authentication techniques

Signed-off-by: William Woodruff <william@yossarian.net>
This commit is contained in:
William Woodruff 2024-05-03 12:37:01 -04:00
parent 2862bc2ac6
commit 18a8b12f7a
No known key found for this signature in database
2 changed files with 28 additions and 1 deletions

View File

@ -33,6 +33,12 @@ module Homebrew
# @api private # @api private
class InvalidAttestationError < RuntimeError; end class InvalidAttestationError < RuntimeError; end
# Raised if attestation verification cannot continue due to missing
# credentials.
#
# @api private
class GhAuthNeeded < RuntimeError; end
# Returns a path to a suitable `gh` executable for attestation verification. # Returns a path to a suitable `gh` executable for attestation verification.
# #
# @api private # @api private
@ -56,6 +62,7 @@ module Homebrew
# `https://github/OWNER/REPO/.github/workflows/WORKFLOW.yml@REF` format. # `https://github/OWNER/REPO/.github/workflows/WORKFLOW.yml@REF` format.
# #
# @return [Hash] the JSON-decoded response. # @return [Hash] the JSON-decoded response.
# @raise [GhAuthNeeded] on any authentication failures
# @raise [InvalidAttestationError] on any verification failures # @raise [InvalidAttestationError] on any verification failures
# #
# @api private # @api private
@ -69,9 +76,18 @@ module Homebrew
cmd += ["--cert-identity", signing_workflow] if signing_workflow.present? cmd += ["--cert-identity", signing_workflow] if signing_workflow.present?
# Fail early if we have no credentials. The command below invariably
# fails without them, so this saves us a network roundtrip before
# presenting the user with the same error.
credentials = GitHub::API.credentials
raise GhAuthNeeded, "missing credentials" if credentials.blank?
begin begin
output = Utils.safe_popen_read(*cmd) output = Utils.safe_popen_read({ "GH_TOKEN" => credentials }, *cmd)
rescue ErrorDuringExecution => e rescue ErrorDuringExecution => e
# Even if we have credentials, they may be invalid or malformed.
raise GhAuthNeeded, "invalid credentials" if e.status.exitstatus == 4
raise InvalidAttestationError, "attestation verification failed: #{e}" raise InvalidAttestationError, "attestation verification failed: #{e}"
end end
@ -100,6 +116,7 @@ module Homebrew
# This is a specialization of `check_attestation` for homebrew-core. # This is a specialization of `check_attestation` for homebrew-core.
# #
# @return [Hash] the JSON-decoded response # @return [Hash] the JSON-decoded response
# @raise [GhAuthNeeded] on any authentication failures
# @raise [InvalidAttestationError] on any verification failures # @raise [InvalidAttestationError] on any verification failures
# #
# @api private # @api private

View File

@ -1261,6 +1261,16 @@ on_request: installed_on_request?, options:)
ohai "Verifying attestation for #{formula.name}" ohai "Verifying attestation for #{formula.name}"
begin begin
Homebrew::Attestation.check_core_attestation formula.bottle Homebrew::Attestation.check_core_attestation formula.bottle
rescue Homebrew::Attestation::GhAuthNeeded
raise CannotInstallFormulaError, <<~EOS
The bottle for #{formula.name} could not be verified.
This typically indicates a missing GitHub API token, which you
can resolve either by setting `HOMEBREW_GITHUB_API_TOKEN` or
by running:
gh auth login
EOS
rescue Homebrew::Attestation::InvalidAttestationError => e rescue Homebrew::Attestation::InvalidAttestationError => e
raise CannotInstallFormulaError, <<~EOS raise CannotInstallFormulaError, <<~EOS
The bottle for #{formula.name} has an invalid build provenance attestation. The bottle for #{formula.name} has an invalid build provenance attestation.