Module: Pindo::KeychainHelper
- Defined in:
- lib/pindo/module/cert/keychainhelper.rb
Class Method Summary collapse
- .help_backticks(command, print: true) ⇒ Object
- .import_file(path, keychain_path, keychain_password: nil, certificate_password: "", skip_set_partition_list: false, output: false) ⇒ Object
-
.resolve_keychain_password(keychain_path) ⇒ Object
github.com/fastlane/fastlane/issues/14196 Keychain password is needed to set the partition list to prevent Xcode from prompting dialog for keychain password when signing 1.
- .set_partition_list(path, keychain_path, keychain_password: nil, output: false) ⇒ Object
Class Method Details
.help_backticks(command, print: true) ⇒ Object
51 52 53 54 55 56 |
# File 'lib/pindo/module/cert/keychainhelper.rb', line 51 def self.help_backticks(command, print: true) # UI.command(command) if print result = `#{command}` # UI.command_output(result) if print return result end |
.import_file(path, keychain_path, keychain_password: nil, certificate_password: "", skip_set_partition_list: false, output: false) ⇒ Object
9 10 11 12 13 14 15 16 17 18 19 20 21 22 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 49 |
# File 'lib/pindo/module/cert/keychainhelper.rb', line 9 def self.import_file(path, keychain_path, keychain_password: nil, certificate_password: "", skip_set_partition_list: false, output: false) # puts path # puts "Could not find file '#{path}'" unless File.exist?(path) password_part = " -P #{certificate_password.shellescape}" command = "security import #{path.shellescape} -k '#{keychain_path.shellescape}'" command << password_part 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 << " -T /usr/bin/productbuild" # to not be asked for permission when using an installer cert for macOS command << " -T /usr/bin/productsign" # to not be asked for permission when using an installer cert for macOS command << " 1> /dev/null" unless output # puts command # sensitive_command = command.gsub(password_part, " -P ********") # UI.command(sensitive_command) if output Open3.popen3(command) do |stdin, stdout, stderr, thrd| # UI.command_output(stdout.read.to_s) if output # puts "123" # 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? && !skip_set_partition_list # puts "安装成功!" keychain_password ||= resolve_keychain_password(keychain_path) 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("'}' is already installed on this machine") # puts "证书key已经存在,安装完成!" else # puts err # raise Informative, err end end end end |
.resolve_keychain_password(keychain_path) ⇒ Object
github.com/fastlane/fastlane/issues/14196 Keychain password is needed to set the partition list to prevent Xcode from prompting dialog for keychain password when signing
-
Uses keychain password from login keychain if found
-
Prompts user for keychain password and stores it in login keychain for user later
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/pindo/module/cert/keychainhelper.rb', line 116 def self.resolve_keychain_password(keychain_path) keychain_name = File.basename(keychain_path, ".*") server = server_name(keychain_name) # Attempt to find password in keychain for keychain item = Security::InternetPassword.find(server: server) if item keychain_password = item.password # UI.important("Using keychain password from keychain item #{server} in #{keychain_path}") end if keychain_password.nil? # if UI.interactive? # UI.important("Enter the password for #{keychain_path}") # UI.important("This passphrase will be stored in your local keychain with the name #{server} and used in future runs") # UI.important("This prompt can be avoided by specifying the 'keychain_password' option or 'MATCH_KEYCHAIN_PASSWORD' environment variable") keychain_password = FastlaneCore::Helper.ask_password(message: "Password for #{keychain_name} keychain: ", confirm: true, confirmation_message: "Type password for #{keychain_name} keychain again: ") Security::InternetPassword.add(server, "", keychain_password) # else # UI.important("Keychain password for #{keychain_path} was not specified and not found in your keychain. Specify the 'keychain_password' option to prevent the UI permission popup when code signing") # keychain_password = "" # end end return keychain_password end |
.set_partition_list(path, keychain_path, keychain_password: nil, output: false) ⇒ Object
58 59 60 61 62 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 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/pindo/module/cert/keychainhelper.rb', line 58 def self.set_partition_list(path, keychain_path, keychain_password: nil, output: false) # When security supports partition lists, also add the partition IDs # See https://openradar.appspot.com/28524119 if help_backticks('security -h | grep set-key-partition-list', print: false).length > 0 password_part = " -k #{keychain_password.to_s.shellescape}" command = "security set-key-partition-list" command << " -S apple-tool:,apple:,codesign:" command << " -s" # This is a needed in Catalina to prevent "security: SecKeychainItemCopyAccess: A missing value was detected." command << password_part 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)") # Strip keychain password from command output # sensitive_command = command.gsub(password_part, " -k ********") # puts command # UI.command(sensitive_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") keychain_name = File.basename(keychain_path, ".*") # puts "password #{keychain_password}" # puts "keychain #{keychain_name}" # puts "security #{server_name(keychain_name)}" Security::InternetPassword.delete(server: server_name(keychain_name)) # 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") # puts "证书密码错误!" else puts err end end end # Hiding after Open3 finishes # Helper.hide_loading_indicator end end |