Documentation/Nightly/Developers/Mac OS X Code Signing
Contents
Overview
This page contains information on code signing on OS X and on integrating code signing into the Slicer packaging process.
Some useful external references from the Mac Developer Library include:
- About Code Signing
- Distributing Apps Outside the Mac App Store
- OS X Code Signing In Depth
- Developer ID and Gatekeeper
Prerequisites
The Gatekeeper feature in OS X helps protect against malicious software. If a user runs an application downloaded from the internet, Gatekeeper verifies the application's digital signature and displays a warning if verification fails. Reasons verification might fail include the app having been tampered with, or the app not having been signed at all.
Currently the OS X Slicer package is not digitally signed. Therefore, depending on system configuration, Gatekeeper may display a warning and confirmation dialog when running a new Slicer build for the first time.
Developer ID certificate
A Developer ID certificate is required to sign an application for distribution outside of the Mac App Store. Once Slicer is signed with this type of certificate, Gatekeeper's signature verification will succeed and users will be able to run Slicer without warnings.
Only the team agent for an organization in the Apple Developer program has authority to create Developer ID certificates. Certificates can be created using Xcode or on the Apple Developer site: https://developer.apple.com/account/mac/certificate/.
There are two types of Developer ID certificates: Developer ID Application certificate and Developer ID Installer certificate. Only the Developer ID Application certificate is required to sign Slicer. The Developer ID Installer certificate is used to sign installers in .pkg format.
Using a self-signed certificate as opposed to a Developer ID certificate is appropriate while testing the packaging process. To create a self-signed certificate, follow the steps in Obtaining a Signing Identity described in the section titled "To use the Certificate Assistant to create a self-signed signing identity."
App identifier
Code signing an application requires a unique app identifier. If each new build of an application is signed using the same identifier, Gatekeeper will recognize new builds as being an updated version and will transparently run the updated version as usually without requested verification from the user.
The unique app identifier can be specified in different ways:
- implicitly from the value of CFBundleIdentifier in the application's Info.plist
- explicitly on the command line when signing the code (e.g.
codesign -i <identifier>
)
For Slicer, in the first case, the factory could set the CMake variable MACOSX_BUNDLE_GUI_IDENTIFIER (see CMake/MacOSXBundleInfo.plist.in). In the second case, a new CMake variable could be added and used when signing the code.
The unique app identifiers are typically hierarchical names in reverse DNS notation.[1] Therefore, an appropriate identifier could be something like com.kitware.medical.Slicer.
Authentication
Depending on the environment in which code signing is being performed, it may be necessary to take one or more of the following steps to use the codesign tool without user interaction (i.e. authentication):
- Run
security unlock-keychain
, like here - In Keychain Access, edit the certificate's private key to "allow all applications to access this item" (right click on the private key, then choose Get Info)
- Add the signing certificate to the system keychain instead of the login keychain
Also see the following discussions:
- StackOverflow: "User interaction is not allowed" trying to sign an OSX app using codesign
- Apple Developer Forums: code sign wants to sign using key - Doesn't allow or always allow but deny works
Code signing
The codesign command signs the code; its usage is summarized below. See Signing Your Code for more information. Advanced options for specifying requirements and entitlements shouldn't be necessary when signing Slicer.
Tasks
List all certificates to verify the name of the Developer ID Application certificate to use:
certtool y
Sign Slicer using a Developer ID Application certificate:
codesign --deep --force --sign "Developer ID Application: <id>" ./Slicer.app
Sign Slicer using a self-signed certificate (for testing):
codesign --deep --force --sign "<certificate id>" ./Slicer.app
However, note that Apple does not recommend using the --deep option when signing.[2]
Show signing info:
codesign -dv
Show designated requirements[3]:
codesign -d -r- ./Slicer.app
Verify signature (mimic what Gatekeeper does to check your app):
codesign --verify --deep --verbose=2 ./Slicer.app
Integration with CPack
Preliminary testing shows one possible way to integrate code signing into Slicer's packaging process with CPack.
After running fixup_bundle in CMake/SlicerCPackBundleFixup.cmake.in (or outside the function after calling fixup_bundle_with_plugins?), call codesign like:
execute_process( COMMAND codesign --deep --force --sign "<certificate id>" -i "<unique app identifier>" "${app_dir}" )
Note that <certificate id> and <unique app identifier> should be CMake variables.
The process could also verify the signing:
execute_process( COMMAND codesign -dv "${app_dir}" )
Logic could be added to only sign if the required CMake variables are specified.
Note that the CPack Bundle generator can be configured to sign by setting variables such as CPACK_BUNDLE_APPLE_CERT_APP. However, this cannot be used here because Slicer uses the DragNDrop generator (see CMake/SlicerCPack.cmake).
Verifying
See Checking Gatekeeper Conformance and Verifying Your Steps for detailed instructions on how to verify a signed application works with Gatekeeper.
The spctl tool tests code signatures against Gatekeeper policies and manages the security assessment policy subsystem. Some basic commands using the spctl tool are summarized below.
Tasks
List current assessment rules:
spctl --list --type execute
Assess an application or tool:
spctl --assess --type execute ./Slicer.app
Show whether assessment is enabled:
spctl --status
Check if Gatekeeper will accept the app's signature:
spctl -a -t exec -vv ./Slicer.app
Reference list
- ↑ Adding an Info.plist to Single-File Tools, Mac Developer Library—Code Signing Guide
- ↑ Using the codesign Tool's --deep Option Correctly, Mac Developer Library—OS X Code Signing In Depth
- ↑ Code Requirements, Mac Developer Library—OS X Code Signing In Depth