attestation: handle bad configurations better
This commit is contained in:
parent
4aae003a1a
commit
16d547b030
@ -44,6 +44,12 @@ module Homebrew
|
||||
# @api private
|
||||
class GhAuthNeeded < RuntimeError; end
|
||||
|
||||
# Raised if attestation verification cannot continue due to invalid
|
||||
# credentials.
|
||||
#
|
||||
# @api private
|
||||
class GhAuthInvalid < RuntimeError; end
|
||||
|
||||
# Returns whether attestation verification is enabled.
|
||||
#
|
||||
# @api private
|
||||
@ -53,6 +59,7 @@ module Homebrew
|
||||
return true if Homebrew::EnvConfig.verify_attestations?
|
||||
return false if GitHub::API.credentials.blank?
|
||||
return false if ENV.fetch("CI", false)
|
||||
return false if OS.unsupported_configuration?
|
||||
|
||||
Homebrew::EnvConfig.developer? || Homebrew::EnvConfig.devcmdrun?
|
||||
end
|
||||
@ -117,11 +124,14 @@ module Homebrew
|
||||
raise GhAuthNeeded, "missing credentials" if credentials.blank?
|
||||
|
||||
begin
|
||||
result = system_command!(gh_executable, args: cmd, env: { "GH_TOKEN" => credentials },
|
||||
result = system_command!(gh_executable, args: cmd,
|
||||
env: { "GH_TOKEN" => credentials, "GH_HOST" => "github.com" },
|
||||
secrets: [credentials], print_stderr: false, chdir: HOMEBREW_TEMP)
|
||||
rescue ErrorDuringExecution => e
|
||||
# Even if we have credentials, they may be invalid or malformed.
|
||||
raise GhAuthNeeded, "invalid credentials" if e.status.exitstatus == 4
|
||||
if e.status.exitstatus == 4 || e.stderr.include?("HTTP 401: Bad credentials")
|
||||
raise GhAuthInvalid, "invalid credentials"
|
||||
end
|
||||
|
||||
raise InvalidAttestationError, "attestation verification failed: #{e}"
|
||||
end
|
||||
|
@ -1284,6 +1284,22 @@ on_request: installed_on_request?, options:)
|
||||
ohai "Verifying attestation for #{formula.name}"
|
||||
begin
|
||||
Homebrew::Attestation.check_core_attestation formula.bottle
|
||||
rescue Homebrew::Attestation::GhAuthInvalid
|
||||
# Only raise an error if we explicitly opted-in to verification.
|
||||
raise CannotInstallFormulaError, <<~EOS if Homebrew::EnvConfig.verify_attestations?
|
||||
The bottle for #{formula.name} could not be verified.
|
||||
|
||||
This typically indicates an invalid GitHub API token.
|
||||
|
||||
If you have `HOMEBREW_GITHUB_API_TOKEN` set, check it is correct
|
||||
or unset it and instead run:
|
||||
|
||||
gh auth login
|
||||
EOS
|
||||
|
||||
# If we didn't explicitly opt-in, then quietly opt-out in the case of invalid credentials.
|
||||
# Based on user reports, a significant number of users are running with stale tokens.
|
||||
ENV["HOMEBREW_NO_VERIFY_ATTESTATIONS"] = "1"
|
||||
rescue Homebrew::Attestation::GhAuthNeeded
|
||||
raise CannotInstallFormulaError, <<~EOS
|
||||
The bottle for #{formula.name} could not be verified.
|
||||
|
@ -115,7 +115,7 @@ RSpec.describe Homebrew::Attestation do
|
||||
expect(described_class).to receive(:system_command!)
|
||||
.with(fake_gh, args: ["attestation", "verify", cached_download, "--repo",
|
||||
described_class::HOMEBREW_CORE_REPO, "--format", "json"],
|
||||
env: { "GH_TOKEN" => fake_gh_creds }, secrets: [fake_gh_creds],
|
||||
env: { "GH_TOKEN" => fake_gh_creds, "GH_HOST" => "github.com" }, secrets: [fake_gh_creds],
|
||||
print_stderr: false, chdir: HOMEBREW_TEMP)
|
||||
.and_raise(ErrorDuringExecution.new(["foo"], status: fake_error_status))
|
||||
|
||||
@ -132,14 +132,14 @@ RSpec.describe Homebrew::Attestation do
|
||||
expect(described_class).to receive(:system_command!)
|
||||
.with(fake_gh, args: ["attestation", "verify", cached_download, "--repo",
|
||||
described_class::HOMEBREW_CORE_REPO, "--format", "json"],
|
||||
env: { "GH_TOKEN" => fake_gh_creds }, secrets: [fake_gh_creds],
|
||||
env: { "GH_TOKEN" => fake_gh_creds, "GH_HOST" => "github.com" }, secrets: [fake_gh_creds],
|
||||
print_stderr: false, chdir: HOMEBREW_TEMP)
|
||||
.and_raise(ErrorDuringExecution.new(["foo"], status: fake_auth_status))
|
||||
|
||||
expect do
|
||||
described_class.check_attestation fake_bottle,
|
||||
described_class::HOMEBREW_CORE_REPO
|
||||
end.to raise_error(described_class::GhAuthNeeded)
|
||||
end.to raise_error(described_class::GhAuthInvalid)
|
||||
end
|
||||
|
||||
it "raises when gh returns invalid JSON" do
|
||||
@ -149,7 +149,7 @@ RSpec.describe Homebrew::Attestation do
|
||||
expect(described_class).to receive(:system_command!)
|
||||
.with(fake_gh, args: ["attestation", "verify", cached_download, "--repo",
|
||||
described_class::HOMEBREW_CORE_REPO, "--format", "json"],
|
||||
env: { "GH_TOKEN" => fake_gh_creds }, secrets: [fake_gh_creds],
|
||||
env: { "GH_TOKEN" => fake_gh_creds, "GH_HOST" => "github.com" }, secrets: [fake_gh_creds],
|
||||
print_stderr: false, chdir: HOMEBREW_TEMP)
|
||||
.and_return(fake_result_invalid_json)
|
||||
|
||||
@ -166,7 +166,7 @@ RSpec.describe Homebrew::Attestation do
|
||||
expect(described_class).to receive(:system_command!)
|
||||
.with(fake_gh, args: ["attestation", "verify", cached_download, "--repo",
|
||||
described_class::HOMEBREW_CORE_REPO, "--format", "json"],
|
||||
env: { "GH_TOKEN" => fake_gh_creds }, secrets: [fake_gh_creds],
|
||||
env: { "GH_TOKEN" => fake_gh_creds, "GH_HOST" => "github.com" }, secrets: [fake_gh_creds],
|
||||
print_stderr: false, chdir: HOMEBREW_TEMP)
|
||||
.and_return(fake_json_resp_wrong_sub)
|
||||
|
||||
@ -183,7 +183,7 @@ RSpec.describe Homebrew::Attestation do
|
||||
expect(described_class).to receive(:system_command!)
|
||||
.with(fake_gh, args: ["attestation", "verify", cached_download, "--repo",
|
||||
described_class::HOMEBREW_CORE_REPO, "--format", "json"],
|
||||
env: { "GH_TOKEN" => fake_gh_creds }, secrets: [fake_gh_creds],
|
||||
env: { "GH_TOKEN" => fake_gh_creds, "GH_HOST" => "github.com" }, secrets: [fake_gh_creds],
|
||||
print_stderr: false, chdir: HOMEBREW_TEMP)
|
||||
.and_return(fake_result_json_resp)
|
||||
|
||||
@ -204,7 +204,7 @@ RSpec.describe Homebrew::Attestation do
|
||||
expect(described_class).to receive(:system_command!)
|
||||
.with(fake_gh, args: ["attestation", "verify", cached_download, "--repo",
|
||||
described_class::HOMEBREW_CORE_REPO, "--format", "json"],
|
||||
env: { "GH_TOKEN" => fake_gh_creds }, secrets: [fake_gh_creds],
|
||||
env: { "GH_TOKEN" => fake_gh_creds, "GH_HOST" => "github.com" }, secrets: [fake_gh_creds],
|
||||
print_stderr: false, chdir: HOMEBREW_TEMP)
|
||||
.and_return(fake_result_json_resp)
|
||||
|
||||
@ -215,7 +215,7 @@ RSpec.describe Homebrew::Attestation do
|
||||
expect(described_class).to receive(:system_command!)
|
||||
.with(fake_gh, args: ["attestation", "verify", cached_download, "--repo",
|
||||
described_class::HOMEBREW_CORE_REPO, "--format", "json"],
|
||||
env: { "GH_TOKEN" => fake_gh_creds }, secrets: [fake_gh_creds],
|
||||
env: { "GH_TOKEN" => fake_gh_creds, "GH_HOST" => "github.com" }, secrets: [fake_gh_creds],
|
||||
print_stderr: false, chdir: HOMEBREW_TEMP)
|
||||
.once
|
||||
.and_raise(described_class::InvalidAttestationError)
|
||||
@ -223,7 +223,7 @@ RSpec.describe Homebrew::Attestation do
|
||||
expect(described_class).to receive(:system_command!)
|
||||
.with(fake_gh, args: ["attestation", "verify", cached_download, "--repo",
|
||||
described_class::BACKFILL_REPO, "--format", "json"],
|
||||
env: { "GH_TOKEN" => fake_gh_creds }, secrets: [fake_gh_creds],
|
||||
env: { "GH_TOKEN" => fake_gh_creds, "GH_HOST" => "github.com" }, secrets: [fake_gh_creds],
|
||||
print_stderr: false, chdir: HOMEBREW_TEMP)
|
||||
.and_return(fake_result_json_resp_backfill)
|
||||
|
||||
@ -234,7 +234,7 @@ RSpec.describe Homebrew::Attestation do
|
||||
expect(described_class).to receive(:system_command!)
|
||||
.with(fake_gh, args: ["attestation", "verify", cached_download, "--repo",
|
||||
described_class::HOMEBREW_CORE_REPO, "--format", "json"],
|
||||
env: { "GH_TOKEN" => fake_gh_creds }, secrets: [fake_gh_creds],
|
||||
env: { "GH_TOKEN" => fake_gh_creds, "GH_HOST" => "github.com" }, secrets: [fake_gh_creds],
|
||||
print_stderr: false, chdir: HOMEBREW_TEMP)
|
||||
.once
|
||||
.and_raise(described_class::InvalidAttestationError)
|
||||
@ -242,7 +242,7 @@ RSpec.describe Homebrew::Attestation do
|
||||
expect(described_class).to receive(:system_command!)
|
||||
.with(fake_gh, args: ["attestation", "verify", cached_download, "--repo",
|
||||
described_class::BACKFILL_REPO, "--format", "json"],
|
||||
env: { "GH_TOKEN" => fake_gh_creds }, secrets: [fake_gh_creds],
|
||||
env: { "GH_TOKEN" => fake_gh_creds, "GH_HOST" => "github.com" }, secrets: [fake_gh_creds],
|
||||
print_stderr: false, chdir: HOMEBREW_TEMP)
|
||||
.and_return(fake_result_json_resp_too_new)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user