Skip to content

Instantly share code, notes, and snippets.

@phani92
Last active July 11, 2024 09:43
Show Gist options
  • Save phani92/6ba7b97266ec6144455582c497e00fa3 to your computer and use it in GitHub Desktop.
Save phani92/6ba7b97266ec6144455582c497e00fa3 to your computer and use it in GitHub Desktop.
Fix (action) for the fastlane's issue of downloading intermediate certificate with match [issue](https://github.com/fastlane/fastlane/issues/20902)
require 'tempfile'
require 'open3'
INTERMEDIATE_CERTIFICATES = [
{
OU: 'G1',
url: 'https://www.apple.com/certificateauthority/DeveloperIDCA.cer'
},
{
OU: 'G2',
url: 'https://www.apple.com/certificateauthority/DeveloperIDG2CA.cer'
},
]
module Fastlane
module Actions
class GetIntermediateCertificateAction < Action
def self.run(params)
# Display user input params
UI.message "keychain_name: #{params[:keychain_name]}"
UI.message "certificate_id: #{params[:certificate]}"
# Fetch Intermediate certificates
issuer = sh("security find-certificate -c \"#{params[:certificate]}\" -p \"#{params[:keychain_name]}\" | openssl x509 -noout -issuer ").match(/(?<=OU=)(.*?),/)[1]
cert_url = INTERMEDIATE_CERTIFICATES.find { |c| c[:OU] == issuer }
if cert_url.nil?
UI.user_error!("Did not find the relevant CA Issuers URI for the Issuer. Please check the array 'INTERMEDIATE_CERTIFICATES' and the 'OU' value of Issuer.")
else
cert_url = cert_url.fetch(:url)
UI.message "Certificate Download url: #{cert_url}"
end
# Download the certificate
file = Tempfile.new(File.basename(cert_url))
filename = file.path
keychain = params[:keychain_name]
keychain = "-k #{keychain.shellescape}" unless keychain.empty?
# build command
import_command = "curl -f -o #{filename} #{cert_url} && security import #{filename} #{keychain}"
# Executes command
stdout, stderr, status = Open3.capture3(import_command)
unless status.success?
unless /The specified item already exists in the keychain./ =~ stderr
UI.user_error!("Could not install certificate")
UI.command_output(stdout)
UI.command_output(stderr)
end
UI.verbose("The Certificate was already installed")
return true
end
end
#####################################################
# @!group Documentation
#####################################################
def self.description
"Fetch and installs the intermediate certificates required for codesigning."
end
def self.details
"You can use this action to install an intermediate certificate which is required to build the signing certificate chain."
end
def self.available_options
[
FastlaneCore::ConfigItem.new(key: :keychain_name,
description: "Keychain - where the certificate shall be installed",
verify_block: proc do |value|
UI.user_error!("Keychain name is not specified, pass using `keychain_name: \"name of keychain\"`") unless (value and not value.empty?)
end,
default_value: "login.keychain-db",
type: String,
optional: false),
FastlaneCore::ConfigItem.new(key: :certificate,
description: "The parent certificate for which the intermediate certificates are being installed",
is_string: true,
default_value: "Developer ID",
verify_block: proc do |value|
UI.user_error!("No certificate given, pass using `certificate: \"certificate_name\"`") unless (value and not value.empty?)
end,
type: String,
optional: false),
]
end
def self.authors
["phani92"]
end
def self.is_supported?(platform)
[:ios, :mac].include?(platform)
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment