attestation: strict typechecking

Signed-off-by: William Woodruff <william@yossarian.net>
This commit is contained in:
William Woodruff 2024-04-09 11:03:41 -04:00
parent 2efef36313
commit 6e10001d49
No known key found for this signature in database

View File

@ -1,4 +1,4 @@
# typed: true # typed: strict
# frozen_string_literal: true # frozen_string_literal: true
require "date" require "date"
@ -28,7 +28,7 @@ module Homebrew
# malicious backfilled signatures. # malicious backfilled signatures.
# #
# @api private # @api private
BACKFILL_CUTOFF = DateTime.new(2024, 3, 14).freeze BACKFILL_CUTOFF = T.let(DateTime.new(2024, 3, 14).freeze, DateTime)
# Raised when attestation verification fails. # Raised when attestation verification fails.
# #
@ -38,13 +38,14 @@ module Homebrew
# 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
sig { returns(Pathname) }
def self.gh_executable def self.gh_executable
# NOTE: We disable HOMEBREW_VERIFY_ATTESTATIONS when installing `gh` itself, # NOTE: We disable HOMEBREW_VERIFY_ATTESTATIONS when installing `gh` itself,
# to prevent a cycle during bootstrapping. This can eventually be resolved # to prevent a cycle during bootstrapping. This can eventually be resolved
# by vendoring a pure-Ruby Sigstore verifier client. # by vendoring a pure-Ruby Sigstore verifier client.
@gh_executable ||= with_env("HOMEBREW_VERIFY_ATTESTATIONS" => nil) do @gh_executable ||= T.let(with_env("HOMEBREW_VERIFY_ATTESTATIONS" => nil) do
ensure_executable!("gh") ensure_executable!("gh")
end end, T.nilable(Pathname))
end end
# Verifies the given bottle against a cryptographic attestation of build provenance. # Verifies the given bottle against a cryptographic attestation of build provenance.
@ -60,6 +61,10 @@ module Homebrew
# @raise [InvalidAttestationError] on any verification failures # @raise [InvalidAttestationError] on any verification failures
# #
# @api private # @api private
sig {
params(bottle: Bottle, signing_repo: String,
signing_workflow: T.nilable(String)).returns(T::Hash[T.untyped, T.untyped])
}
def self.check_attestation(bottle, signing_repo, signing_workflow = nil) def self.check_attestation(bottle, signing_repo, signing_workflow = nil)
cmd = [gh_executable, "attestation", "verify", bottle.cached_download, "--repo", signing_repo, "--format", cmd = [gh_executable, "attestation", "verify", bottle.cached_download, "--repo", signing_repo, "--format",
"json"] "json"]
@ -92,6 +97,7 @@ module Homebrew
# @raise [InvalidAttestationError] on any verification failures # @raise [InvalidAttestationError] on any verification failures
# #
# @api private # @api private
sig { params(bottle: Bottle).returns(T::Hash[T.untyped, T.untyped]) }
def self.check_core_attestation(bottle) def self.check_core_attestation(bottle)
begin begin
attestation = check_attestation bottle, HOMEBREW_CORE_REPO attestation = check_attestation bottle, HOMEBREW_CORE_REPO