Sign Mobileconfig – Apple .mobileconfig configuration profile signing

Signed configuration profile is being installed on iPhone
Signed configuration profile is being installed on iPhone

During installation on iOS/macOS, digitally signed Apple configuration profile is shown with a green tick and corresponding note providing trust for the user. It is possible to use this command in Terminal to sign a .mobileconfig profile. However, it is easier to use a script which will request certificate file, private key and trust chain certificate in dialog.

First, create a new Automator Service named Sign MobileConfig.workflow in user folder
~/Library/Services

Then drag Run AppleScript element into Automator window, and fill it with the following code:

property preferences_file : "com.pozhvanov.mcfgsigner.plist"
(*       property preferences_path : "~/Library/Preferences/"       *)
to SelectSignerPEM(title_SignerPEM, folder_location_SignerPEM)
       set SignerPEM to choose file with prompt title_SignerPEM default location folder_location_SignerPEM of type {"public.x509-certificate", "public.text"}
       return SignerPEM as alias
end SelectSignerPEM
to SelectKeyPEM(title_KeyPEM, folder_location_KeyPEM)
       set KeyPEM to choose file with prompt title_KeyPEM default location folder_location_KeyPEM of type {"public.item", "com.apple.keynote.key", "public.x509-certificate", "public.text"}
       return KeyPEM as alias
end SelectKeyPEM
to SelectChainPEM(title_ChainPEM, folder_location_ChainPEM)
       set ChainPEM to choose file with prompt title_ChainPEM default location folder_location_ChainPEM of type {"public.x509-certificate", "public.text"}
       return ChainPEM as alias
end SelectChainPEM
on replace_chars(this_text, search_string, replacement_string)
       set AppleScript's text item delimiters to the search_string
       set the item_list to every text item of this_text
       set AppleScript's text item delimiters to the replacement_string
       set this_text to the item_list as string
       set AppleScript's text item delimiters to ""
       return this_text
end replace_chars
to checkPreferences()
       tell application "System Events"
              if exists file preferences_file of (path to preferences from user domain) then
                     return 1
              else
                     return 0
              end if
       end tell
end checkPreferences
on run {input, parameters}
       set preferences_path to POSIX path of (path to preferences from user domain) as string
       if user locale of (get system info) starts with "ru" then
              set lang to "ru"
              set msg_title_SignerPEM to "Выберите сертификат электронной подписи:"
              set msg_title_KeyPEM to "Выберите частный ключ:"
              set msg_title_ChainPEM to "Выберите сертификат цепочки доверия:"
              set msg_result_1 to "Подписание завершено. Обработано файлов: "
       else
              set lang to "en"
              set msg_title_SignerPEM to "Select signing certificate:"
              set msg_title_KeyPEM to "Select private key:"
              set msg_title_ChainPEM to "Select certificate trust chain:"
              set msg_result_1 to "Signing completed. Files processed: "
       end if
       set xml_default_path to POSIX path of (path to documents folder) as text
       set xml_signer_path to xml_default_path
       set xml_key_path to xml_default_path
       set xml_chain_path to xml_default_path
       (*  Read preferences from Preferences File  *)
       if checkPreferences() is equal to 1 then
              set the mcfgsigner_plist to preferences_path & preferences_file
              tell application "System Events"
                     tell property list file mcfgsigner_plist
                            tell contents
                                   if exists property list item "signer_path" then
                                          set xml_signer_path to value of property list item "signer_path"
                                   end if
                                   if exists property list item "key_path" then
                                          set xml_key_path to value of property list item "key_path"
                                   end if
                                   if exists property list item "chain_path" then
                                          set xml_chain_path to value of property list item "chain_path"
                                   end if
                            end tell
                     end tell
              end tell
       end if
       
       set SignerPEM to SelectSignerPEM(msg_title_SignerPEM, xml_signer_path)
       set KeyPEM to SelectKeyPEM(msg_title_KeyPEM, xml_key_path)
       set ChainPEM to SelectChainPEM(msg_title_ChainPEM, xml_chain_path)
       
       tell application "Finder"
              set xml_signer_path to (POSIX path of (container of SignerPEM as alias)) as string
              set xml_key_path to (POSIX path of (container of KeyPEM as alias)) as string
              set xml_chain_path to (POSIX path of (container of ChainPEM as alias)) as string
       end tell
       
       set CommandString to "openssl smime -sign -signer \"" & POSIX path of (SignerPEM as string) & "\" -inkey \"" & POSIX path of (KeyPEM as string) & "\" -certfile \"" & POSIX path of (ChainPEM as string) & "\" -nodetach -outform der"
       
       repeat with i in input as list
              set CommandString to CommandString & " -in \"" & POSIX path of (i as text) & "\" -out \"" & replace_chars(POSIX path of (i as text), ".mobileconfig", ".signed.mobileconfig") & "\""
              do shell script CommandString
       end repeat
       
       (*  Save preferences in Preferences File  *)
       tell application "System Events"
              set mcfgsigner_dictionary to make new property list item with properties {kind:record}
              set mcfgsigner_plist to preferences_path & preferences_file
              set this_plist to make new property list file with properties {contents:mcfgsigner_dictionary, name:mcfgsigner_plist}
              make new property list item at end of property list items of contents of this_plist with properties {kind:string, name:"signer_path", value:xml_signer_path}
              make new property list item at end of property list items of contents of this_plist with properties {kind:string, name:"key_path", value:xml_key_path}
              make new property list item at end of property list items of contents of this_plist with properties {kind:string, name:"chain_path", value:xml_chain_path}
       end tell
       display notification (msg_result_1 & ((count of input) as list) as text) with title "MobileConfig Signer" sound name "Submarine"
       return (msg_result_1 & ((count of input) as list) as text)
end run

Leave a Reply