Class: FastlaneCore::CertChecker

Inherits:
Object
  • Object
show all
Defined in:
fastlane_core/lib/fastlane_core/cert_checker.rb

Overview

This class checks if a specific certificate is installed on the current mac

Class Method Summary collapse

Class Method Details

.install_wwdr_certificateObject


63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'fastlane_core/lib/fastlane_core/cert_checker.rb', line 63

def self.install_wwdr_certificate
  url = 'https://developer.apple.com/certificationauthority/AppleWWDRCA.cer'
  file = Tempfile.new('AppleWWDRCA')
  filename = file.path
  keychain = wwdr_keychain
  keychain = "-k #{keychain.shellescape}" unless keychain.empty?

  require 'open3'

  import_command = "curl -f -o #{filename} #{url} && security import #{filename} #{keychain}"
  UI.verbose("Installing WWDR Cert: #{import_command}")

  stdout, stderr, _status = Open3.capture3(import_command)
  if FastlaneCore::Globals.verbose?
    UI.command_output(stdout)
    UI.command_output(stderr)
  end

  unless $?.success?
    UI.verbose("Failed to install WWDR Certificate, checking output to see why")
    # Check the command output, WWDR might already exist
    unless /The specified item already exists in the keychain./ =~ stderr
      UI.user_error!("Could not install WWDR certificate")
    end
    UI.verbose("WWDR Certificate was already installed")
  end
  return true
end

.installed?(path, in_keychain: nil) ⇒ Boolean

Returns:


9
10
11
12
13
14
15
16
# File 'fastlane_core/lib/fastlane_core/cert_checker.rb', line 9

def self.installed?(path, in_keychain: nil)
  UI.user_error!("Could not find file '#{path}'") unless File.exist?(path)

  ids = installed_identies(in_keychain: in_keychain)
  finger_print = sha1_fingerprint(path)

  return ids.include?(finger_print)
end

.installed_identies(in_keychain: nil) ⇒ Object


23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'fastlane_core/lib/fastlane_core/cert_checker.rb', line 23

def self.installed_identies(in_keychain: nil)
  install_wwdr_certificate unless wwdr_certificate_installed?

  available = list_available_identities(in_keychain: in_keychain)
  # Match for this text against word boundaries to avoid edge cases around multiples of 10 identities!
  if /\b0 valid identities found\b/ =~ available
    UI.error([
      "There are no local code signing identities found.",
      "You can run" << " `security find-identity -v -p codesigning #{in_keychain}".rstrip << "` to get this output.",
      "This Stack Overflow thread has more information: https://stackoverflow.com/q/35390072/774.",
      "(Check in Keychain Access for an expired WWDR certificate: https://stackoverflow.com/a/35409835/774 has more info.)"
    ].join("\n"))
  end

  ids = []
  available.split("\n").each do |current|
    next if current.include?("REVOKED")
    begin
      (ids << current.match(/.*\) ([[:xdigit:]]*) \".*/)[1])
    rescue
      # the last line does not match
    end
  end

  return ids
end

.is_installed?(path) ⇒ Boolean

Legacy Method, use `installed?` instead

Returns:


19
20
21
# File 'fastlane_core/lib/fastlane_core/cert_checker.rb', line 19

def self.is_installed?(path)
  installed?(path)
end

.list_available_identities(in_keychain: nil) ⇒ Object


50
51
52
53
54
# File 'fastlane_core/lib/fastlane_core/cert_checker.rb', line 50

def self.list_available_identities(in_keychain: nil)
  commands = ['security find-identity -v -p codesigning']
  commands << in_keychain if in_keychain
  `#{commands.join(' ')}`
end

.sha1_fingerprint(path) ⇒ Object


107
108
109
110
111
112
113
114
# File 'fastlane_core/lib/fastlane_core/cert_checker.rb', line 107

def self.sha1_fingerprint(path)
  file_data = File.read(path.to_s)
  cert = OpenSSL::X509::Certificate.new(file_data)
  return OpenSSL::Digest::SHA1.new(cert.to_der).to_s.upcase
rescue => error
  UI.error(error)
  UI.user_error!("Error parsing certificate '#{path}'")
end

.wwdr_certificate_installed?Boolean

Returns:


56
57
58
59
60
61
# File 'fastlane_core/lib/fastlane_core/cert_checker.rb', line 56

def self.wwdr_certificate_installed?
  certificate_name = "Apple Worldwide Developer Relations Certification Authority"
  keychain = wwdr_keychain
  response = Helper.backticks("security find-certificate -c '#{certificate_name}' #{keychain.shellescape}", print: FastlaneCore::Globals.verbose?)
  return response.include?("attributes:")
end

.wwdr_keychainObject


92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'fastlane_core/lib/fastlane_core/cert_checker.rb', line 92

def self.wwdr_keychain
  priority = [
    "security list-keychains -d user",
    "security default-keychain -d user"
  ]
  priority.each do |command|
    keychains = Helper.backticks(command, print: FastlaneCore::Globals.verbose?).split("\n")
    unless keychains.empty?
      # Select first keychain name from returned keychains list
      return keychains[0].strip.tr('"', '')
    end
  end
  return ""
end