Skip to content

Commit

Permalink
fix(match): propagate keychain when installing wwdr certificates
Browse files Browse the repository at this point in the history
  • Loading branch information
rabbitinspace committed Oct 17, 2023
1 parent 1732b60 commit f065e6d
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 22 deletions.
17 changes: 9 additions & 8 deletions fastlane_core/lib/fastlane_core/cert_checker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class CertChecker
def self.installed?(path, in_keychain: nil)
UI.user_error!("Could not find file '#{path}'") unless File.exist?(path)

in_keychain &&= FastlaneCore::Helper.keychain_path(in_keychain)
ids = installed_identies(in_keychain: in_keychain)
ids += installed_installers(in_keychain: in_keychain)
finger_print = sha1_fingerprint(path)
Expand All @@ -52,7 +53,7 @@ def self.is_installed?(path)
end

def self.installed_identies(in_keychain: nil)
install_missing_wwdr_certificates
install_missing_wwdr_certificates(in_keychain: in_keychain)

available = list_available_identities(in_keychain: in_keychain)
# Match for this text against word boundaries to avoid edge cases around multiples of 10 identities!
Expand Down Expand Up @@ -111,12 +112,12 @@ def self.list_available_developer_id_installer(in_keychain: nil)
`#{commands.join(' ')}`
end

def self.installed_wwdr_certificates
def self.installed_wwdr_certificates(keychain)
certificate_name = "Apple Worldwide Developer Relations"

# Find all installed WWDRCA certificates
installed_certs = []
Helper.backticks("security find-certificate -a -c '#{certificate_name}' -p #{wwdr_keychain.shellescape}")
Helper.backticks("security find-certificate -a -c '#{certificate_name}' -p #{keychain.shellescape}")
.lines
.each do |line|
if line.start_with?('-----BEGIN CERTIFICATE-----')
Expand All @@ -135,20 +136,20 @@ def self.installed_wwdr_certificates
.compact
end

def self.install_missing_wwdr_certificates
def self.install_missing_wwdr_certificates(in_keychain: nil)
# Install all Worldwide Developer Relations Intermediate Certificates listed here: https://www.apple.com/certificateauthority/
missing = WWDRCA_CERTIFICATES.map { |c| c[:alias] } - installed_wwdr_certificates
keychain = in_keychain || wwdr_keychain
missing = WWDRCA_CERTIFICATES.map { |c| c[:alias] } - installed_wwdr_certificates(keychain)
missing.each do |cert_alias|
install_wwdr_certificate(cert_alias)
install_wwdr_certificate(cert_alias, keychain)
end
missing.count
end

def self.install_wwdr_certificate(cert_alias)
def self.install_wwdr_certificate(cert_alias, keychain)
url = WWDRCA_CERTIFICATES.find { |c| c[:alias] == cert_alias }.fetch(:url)
file = Tempfile.new([File.basename(url, ".cer"), ".cer"])
filename = file.path
keychain = wwdr_keychain
keychain = "-k #{keychain.shellescape}" unless keychain.empty?

# Attempts to fix an issue installing WWDR cert tends to fail on CIs
Expand Down
32 changes: 18 additions & 14 deletions fastlane_core/spec/cert_checker_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class ProcessStatusMock

describe '#installed_identies' do
it 'should print an error when no local code signing identities are found' do
allow(FastlaneCore::CertChecker).to receive(:wwdr_keychain).and_return('login.keychain')
allow(FastlaneCore::CertChecker).to receive(:installed_wwdr_certificates).and_return(['G2', 'G3', 'G4', 'G5', 'G6'])
allow(FastlaneCore::CertChecker).to receive(:list_available_identities).and_return(" 0 valid identities found\n")
expect(FastlaneCore::UI).to receive(:error).with(/There are no local code signing identities found/)
Expand All @@ -19,6 +20,7 @@ class ProcessStatusMock
end

it 'should not be fooled by 10 local code signing identities available' do
allow(FastlaneCore::CertChecker).to receive(:wwdr_keychain).and_return('login.keychain')
allow(FastlaneCore::CertChecker).to receive(:installed_wwdr_certificates).and_return(['G2', 'G3', 'G4', 'G5', 'G6'])
allow(FastlaneCore::CertChecker).to receive(:list_available_identities).and_return(" 10 valid identities found\n")
expect(FastlaneCore::UI).not_to(receive(:error))
Expand All @@ -45,7 +47,7 @@ class ProcessStatusMock
allow(Digest::SHA256).to receive(:hexdigest).with(cert.to_der).and_return('bdd4ed6e74691f0c2bfd01be0296197af1379e0418e2d300efa9c3bef642ca30')
allow(OpenSSL::X509::Certificate).to receive(:new).and_return(cert)

expect(FastlaneCore::CertChecker.installed_wwdr_certificates).to eq(['G6'])
expect(FastlaneCore::CertChecker.installed_wwdr_certificates(FastlaneCore::CertChecker.wwdr_keychain)).to eq(['G6'])
end

it "should return an empty array if unknown WWDR certificates are found" do
Expand All @@ -55,44 +57,46 @@ class ProcessStatusMock

allow(OpenSSL::X509::Certificate).to receive(:new).and_return(cert)

expect(FastlaneCore::CertChecker.installed_wwdr_certificates).to eq([])
expect(FastlaneCore::CertChecker.installed_wwdr_certificates(FastlaneCore::CertChecker.wwdr_keychain)).to eq([])
end
end

describe '#install_missing_wwdr_certificates' do
it 'should install all official WWDR certificates' do
allow(FastlaneCore::CertChecker).to receive(:wwdr_keychain).and_return('login.keychain')
allow(FastlaneCore::CertChecker).to receive(:installed_wwdr_certificates).and_return([])
expect(FastlaneCore::CertChecker).to receive(:install_wwdr_certificate).with('G2')
expect(FastlaneCore::CertChecker).to receive(:install_wwdr_certificate).with('G3')
expect(FastlaneCore::CertChecker).to receive(:install_wwdr_certificate).with('G4')
expect(FastlaneCore::CertChecker).to receive(:install_wwdr_certificate).with('G5')
expect(FastlaneCore::CertChecker).to receive(:install_wwdr_certificate).with('G6')
expect(FastlaneCore::CertChecker).to receive(:install_wwdr_certificate).with('G2', FastlaneCore::CertChecker.wwdr_keychain)
expect(FastlaneCore::CertChecker).to receive(:install_wwdr_certificate).with('G3', FastlaneCore::CertChecker.wwdr_keychain)
expect(FastlaneCore::CertChecker).to receive(:install_wwdr_certificate).with('G4', FastlaneCore::CertChecker.wwdr_keychain)
expect(FastlaneCore::CertChecker).to receive(:install_wwdr_certificate).with('G5', FastlaneCore::CertChecker.wwdr_keychain)
expect(FastlaneCore::CertChecker).to receive(:install_wwdr_certificate).with('G6', FastlaneCore::CertChecker.wwdr_keychain)
FastlaneCore::CertChecker.install_missing_wwdr_certificates
end

it 'should install the missing official WWDR certificate' do
allow(FastlaneCore::CertChecker).to receive(:wwdr_keychain).and_return('login.keychain')
allow(FastlaneCore::CertChecker).to receive(:installed_wwdr_certificates).and_return(['G2', 'G3', 'G4', 'G5'])
expect(FastlaneCore::CertChecker).to receive(:install_wwdr_certificate).with('G6')
expect(FastlaneCore::CertChecker).to receive(:install_wwdr_certificate).with('G6', FastlaneCore::CertChecker.wwdr_keychain)
FastlaneCore::CertChecker.install_missing_wwdr_certificates
end

it 'should download the WWDR certificate from correct URL' do
allow(FastlaneCore::CertChecker).to receive(:wwdr_keychain).and_return('login.keychain')

expect(Open3).to receive(:capture3).with(include('https://www.apple.com/certificateauthority/AppleWWDRCAG2.cer')).and_return(["", "", success_status])
FastlaneCore::CertChecker.install_wwdr_certificate('G2')
FastlaneCore::CertChecker.install_wwdr_certificate('G2', FastlaneCore::CertChecker.wwdr_keychain)

expect(Open3).to receive(:capture3).with(include('https://www.apple.com/certificateauthority/AppleWWDRCAG3.cer')).and_return(["", "", success_status])
FastlaneCore::CertChecker.install_wwdr_certificate('G3')
FastlaneCore::CertChecker.install_wwdr_certificate('G3', FastlaneCore::CertChecker.wwdr_keychain)

expect(Open3).to receive(:capture3).with(include('https://www.apple.com/certificateauthority/AppleWWDRCAG4.cer')).and_return(["", "", success_status])
FastlaneCore::CertChecker.install_wwdr_certificate('G4')
FastlaneCore::CertChecker.install_wwdr_certificate('G4', FastlaneCore::CertChecker.wwdr_keychain)

expect(Open3).to receive(:capture3).with(include('https://www.apple.com/certificateauthority/AppleWWDRCAG5.cer')).and_return(["", "", success_status])
FastlaneCore::CertChecker.install_wwdr_certificate('G5')
FastlaneCore::CertChecker.install_wwdr_certificate('G5', FastlaneCore::CertChecker.wwdr_keychain)

expect(Open3).to receive(:capture3).with(include('https://www.apple.com/certificateauthority/AppleWWDRCAG6.cer')).and_return(["", "", success_status])
FastlaneCore::CertChecker.install_wwdr_certificate('G6')
FastlaneCore::CertChecker.install_wwdr_certificate('G6', FastlaneCore::CertChecker.wwdr_keychain)
end
end

Expand All @@ -105,7 +109,7 @@ class ProcessStatusMock
expect(FastlaneCore::CertChecker).to receive(:wwdr_keychain).and_return(keychain_name)
expect(FastlaneCore::Helper).to receive(:backticks).with(name_regex).and_return("")

FastlaneCore::CertChecker.installed_wwdr_certificates
FastlaneCore::CertChecker.installed_wwdr_certificates(FastlaneCore::CertChecker.wwdr_keychain)
end

describe 'uses the correct command to import it' do
Expand Down

0 comments on commit f065e6d

Please sign in to comment.