From b8ff4b3d23695c6e248d937c54fe2dbb63ebe108 Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Sun, 14 Jul 2024 11:50:57 -0400 Subject: [PATCH] Widen attestation verification rollout Take 2 of https://github.com/Homebrew/brew/pull/17692 but with: - provide and document `HOMEBREW_NO_VERIFY_ATTESTATIONS` - don't try to run unless there's GitHub credentials - don't try to run unless `gh` is installed - don't try to run in CI While we're here: - split out a `Homebrew::EnvConfig.devcmdrun?` helper method - add some missing `Homebrew::EnvConfig.github_api_token` presence checks --- Library/Homebrew/attestation.rb | 8 ++++---- Library/Homebrew/cmd/developer.rb | 2 +- Library/Homebrew/diagnostic.rb | 4 ++-- Library/Homebrew/env_config.rb | 10 ++++++++++ .../Homebrew/sorbet/rbi/dsl/homebrew/env_config.rbi | 3 +++ Library/Homebrew/utils/analytics.rb | 4 ++-- Library/Homebrew/utils/curl.rb | 2 +- Library/Homebrew/utils/github/api.rb | 4 +++- 8 files changed, 26 insertions(+), 11 deletions(-) diff --git a/Library/Homebrew/attestation.rb b/Library/Homebrew/attestation.rb index 2055fd0f021f0..0ae04cdf5e7ab 100644 --- a/Library/Homebrew/attestation.rb +++ b/Library/Homebrew/attestation.rb @@ -45,13 +45,13 @@ class GhAuthNeeded < RuntimeError; end # @api private sig { returns(T::Boolean) } def self.enabled? - # TODO: allow this undocumented variable until this is rolled out more - # widely and then we can remove or document it. - return false if ENV.fetch("HOMEBREW_NO_VERIFY_ATTESTATIONS", false) + return false if Homebrew::EnvConfig.no_verify_attestations? return true if Homebrew::EnvConfig.verify_attestations? + return false if GitHub::API.credentials.blank? return false if ENV.fetch("CI", false) + return false unless Formula["gh"].any_version_installed? - Homebrew::EnvConfig.developer? + Homebrew::EnvConfig.developer? || Homebrew::EnvConfig.devcmdrun? end # Returns a path to a suitable `gh` executable for attestation verification. diff --git a/Library/Homebrew/cmd/developer.rb b/Library/Homebrew/cmd/developer.rb index f3f43c41e6abf..7788536ea95d9 100644 --- a/Library/Homebrew/cmd/developer.rb +++ b/Library/Homebrew/cmd/developer.rb @@ -36,7 +36,7 @@ def run if env_vars.any? verb = (env_vars.count == 1) ? "is" : "are" puts "Developer mode is enabled because #{env_vars.to_sentence} #{verb} set." - elsif Homebrew::Settings.read("devcmdrun") == "true" + elsif Homebrew::EnvConfig.devcmdrun? puts "Developer mode is enabled." else puts "Developer mode is disabled." diff --git a/Library/Homebrew/diagnostic.rb b/Library/Homebrew/diagnostic.rb index 73d11882fc907..dfb04481d7d03 100644 --- a/Library/Homebrew/diagnostic.rb +++ b/Library/Homebrew/diagnostic.rb @@ -865,7 +865,7 @@ def check_deleted_formula def check_for_unnecessary_core_tap return if Homebrew::EnvConfig.developer? return if Homebrew::EnvConfig.no_install_from_api? - return if Homebrew::Settings.read("devcmdrun") == "true" + return if Homebrew::EnvConfig.devcmdrun? return unless CoreTap.instance.installed? <<~EOS @@ -879,7 +879,7 @@ def check_for_unnecessary_core_tap def check_for_unnecessary_cask_tap return if Homebrew::EnvConfig.developer? return if Homebrew::EnvConfig.no_install_from_api? - return if Homebrew::Settings.read("devcmdrun") == "true" + return if Homebrew::EnvConfig.devcmdrun? cask_tap = CoreCaskTap.instance return unless cask_tap.installed? diff --git a/Library/Homebrew/env_config.rb b/Library/Homebrew/env_config.rb index d77c1c539984e..35b56c45eec87 100644 --- a/Library/Homebrew/env_config.rb +++ b/Library/Homebrew/env_config.rb @@ -379,6 +379,11 @@ module EnvConfig description: "If set, `brew update` will not show the list of newly added formulae/casks.", boolean: true, }, + HOMEBREW_NO_VERIFY_ATTESTATIONS: { + description: "If set, Homebrew not verify cryptographic attestations of build provenance for bottles " \ + "from homebrew-core.", + boolean: true, + }, HOMEBREW_PIP_INDEX_URL: { description: "If set, `brew install` will use this URL to download PyPI package resources.", default_text: "`https://pypi.org/simple`.", @@ -556,5 +561,10 @@ def cask_opts_require_sha? def automatically_set_no_install_from_api? ENV["HOMEBREW_AUTOMATICALLY_SET_NO_INSTALL_FROM_API"].present? end + + sig { returns(T::Boolean) } + def devcmdrun? + Homebrew::Settings.read("devcmdrun") == "true" + end end end diff --git a/Library/Homebrew/sorbet/rbi/dsl/homebrew/env_config.rbi b/Library/Homebrew/sorbet/rbi/dsl/homebrew/env_config.rbi index ae282cccbec4d..2d527e640be92 100644 --- a/Library/Homebrew/sorbet/rbi/dsl/homebrew/env_config.rbi +++ b/Library/Homebrew/sorbet/rbi/dsl/homebrew/env_config.rbi @@ -235,6 +235,9 @@ module Homebrew::EnvConfig sig { returns(T::Boolean) } def no_update_report_new?; end + sig { returns(T::Boolean) } + def no_verify_attestations?; end + sig { returns(T.nilable(::String)) } def pip_index_url; end diff --git a/Library/Homebrew/utils/analytics.rb b/Library/Homebrew/utils/analytics.rb index 1138eb61fe914..44900133b6373 100644 --- a/Library/Homebrew/utils/analytics.rb +++ b/Library/Homebrew/utils/analytics.rb @@ -119,7 +119,7 @@ def report_command_run(command_instance) tags = { command:, ci: ENV["CI"].present?, - devcmdrun: config_true?(:devcmdrun), + devcmdrun: Homebrew::EnvConfig.devcmdrun?, developer: Homebrew::EnvConfig.developer?, } @@ -354,7 +354,7 @@ def default_package_tags prefix:, default_prefix: Homebrew.default_prefix?, developer: Homebrew::EnvConfig.developer?, - devcmdrun: config_true?(:devcmdrun), + devcmdrun: Homebrew::EnvConfig.devcmdrun?, arch: HOMEBREW_PHYSICAL_PROCESSOR, os: HOMEBREW_SYSTEM, } diff --git a/Library/Homebrew/utils/curl.rb b/Library/Homebrew/utils/curl.rb index 7c3a0f8b2ed22..a5fe7bab5fde3 100644 --- a/Library/Homebrew/utils/curl.rb +++ b/Library/Homebrew/utils/curl.rb @@ -352,7 +352,7 @@ def curl_check_http_content(url, url_type, specs: {}, user_agents: [:default], r check_github_api = url_type == SharedAudits::URL_TYPE_HOMEPAGE && details[:status_code] == "404" && repo_details && - Homebrew::EnvConfig.github_api_token + Homebrew::EnvConfig.github_api_token.present? unless check_github_api return "The #{url_type} #{url} is not reachable (HTTP status code #{details[:status_code]})" diff --git a/Library/Homebrew/utils/github/api.rb b/Library/Homebrew/utils/github/api.rb index b683a0b855d4a..d695cf52c17c0 100644 --- a/Library/Homebrew/utils/github/api.rb +++ b/Library/Homebrew/utils/github/api.rb @@ -181,7 +181,9 @@ def self.keychain_username_password end def self.credentials - @credentials ||= Homebrew::EnvConfig.github_api_token || github_cli_token || keychain_username_password + @credentials ||= Homebrew::EnvConfig.github_api_token.presence + @credentials ||= github_cli_token.presence + @credentials ||= keychain_username_password.presence end sig { returns(Symbol) }