Class: FastlaneCore::KeychainImporter

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

Class Method Summary collapse

Class Method Details

.import_file(path, keychain_path, keychain_password: "", certificate_password: "", output: FastlaneCore::Globals.verbose?) ⇒ Object

[View source]

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'fastlane_core/lib/fastlane_core/keychain_importer.rb', line 6

def self.import_file(path, keychain_path, keychain_password: "", certificate_password: "", output: FastlaneCore::Globals.verbose?)
  UI.user_error!("Could not find file '#{path}'") unless File.exist?(path)

  command = "security import #{path.shellescape} -k '#{keychain_path.shellescape}'"
  command << " -P #{certificate_password.shellescape}"
  command << " -T /usr/bin/codesign" # to not be asked for permission when running a tool like `gym` (before Sierra)
  command << " -T /usr/bin/security"
  command << " 1> /dev/null" unless output

  UI.command(command) if output
  Open3.popen3(command) do |stdin, stdout, stderr, thrd|
    UI.command_output(stdout.read.to_s) if output

    # Set partition list only if success since it can be a time consuming process if a lot of keys are installed
    if thrd.value.success?
      set_partition_list(path, keychain_path, keychain_password: keychain_password, output: output)
    else
      # Output verbose if file is already installed since not an error otherwise we will show the whole error
      err = stderr.read.to_s.strip
      if err.include?("SecKeychainItemImport") && err.include?("The specified item already exists in the keychain")
        UI.verbose("'#{File.basename(path)}' is already installed on this machine")
      else
        UI.error(err)
      end
    end
  end
end

.set_partition_list(path, keychain_path, keychain_password: "", output: FastlaneCore::Globals.verbose?) ⇒ Object

[View source]

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'fastlane_core/lib/fastlane_core/keychain_importer.rb', line 34

def self.set_partition_list(path, keychain_path, keychain_password: "", output: FastlaneCore::Globals.verbose?)
  # When security supports partition lists, also add the partition IDs
  # See https://openradar.appspot.com/28524119
  if Helper.backticks('security -h | grep set-key-partition-list', print: false).length > 0
    command = "security set-key-partition-list"
    command << " -S apple-tool:,apple:"
    command << " -k #{keychain_password.to_s.shellescape}"
    command << " #{keychain_path.shellescape}"
    command << " 1> /dev/null" # always disable stdout. This can be very verbose, and leak potentially sensitive info

    # Showing loading indicator as this can take some time if a lot of keys installed
    Helper.show_loading_indicator("Setting key partition list... (this can take a minute if there are a lot of keys installed)")

    UI.command(command) if output
    Open3.popen3(command) do |stdin, stdout, stderr, thrd|
      unless thrd.value.success?
        err = stderr.read.to_s.strip

        # Inform user when no/wrong password was used as its needed to prevent UI permission popup from Xcode when signing
        if err.include?("SecKeychainItemSetAccessWithPassword")
          UI.important("")
          UI.important("Could not configure imported keychain item (certificate) to prevent UI permission popup when code signing\n" \
                   "Check if you supplied the correct `keychain_password` for keychain: `#{keychain_path}`\n" \
                   "#{err}")
          UI.important("")
          UI.important("Please look at the following docs to see how to set a keychain password:")
          UI.important(" - https://docs.fastlane.tools/actions/sync_code_signing")
          UI.important(" - https://docs.fastlane.tools/actions/get_certificates")
        else
          UI.error(err)
        end
      end
    end

    # Hiding after Open3 finishes
    Helper.hide_loading_indicator

  end
end