Wiki
Clone wikiSigning Manager / AdminGuide
Signing Manager Admin Guide
Current Version: 1.2
Overview
Signing Manager is a macOS application for code signing and package signing using remote identities. It includes a CryptoTokenKit extension for presenting X.509 certificates to the macOS keychain for use in cryptographic signing operations using built in commands such as codesign
and productsign
. It can be customized for use with an external system or used with the signing service provided as part of the Signing Manager project.
Requirements
Client: macOS 10.14 or later.
Server: macOS, Linux, or Windows system capable of running Node.js 12 or later.
Certificate and private keys for signing macOS, iOS, watchOS, and iPadOS code and packages.
Client Installation
Signing Manager is distributed as a disk image (dmg) that contains a standard macOS installer package.
To install the package in Finder:
- Double click on the disk image to mount it in Finder.
- Double click on the package in the mounted disk image to start installing the package.
Follow the prompts in the installer package to complete installation.
To install the package via the command line, use the installer
command.
Installed Components
The macOS installer consists of three major components:
- macOS app ("Signing Manager.app") installed in the
/Applications
folder - CryptoTokenKit extension installed in the Signing Manager.app bundle
- CCID driver for notifying macOS to add and remove certificates from the keychain. Installed in
/usr/local/lib/pcsc/drivers/serial/ifd-virtualserial.bundle
. The configuration file for this driver is installed in/etc/reader.conf
.
The installer requires a restart due to the initial installation of the CCID driver.
Signing Service Installation
The server is a Node.js application that runs on macOS, Linux, and Windows. The Node application is bundled with a runtime version of Node for easy deployment. If you are familiar with deploying Node applications, the Node script can be installed from source.
Signing Service Components
The signing service consists of:
signing_service
: Node application binary
settings.json
: Settings JSON file that contains the API keys, certificates and private keys, and other settings
server.key
: Private key for the SSL certificate used to secure communications
server.cert
: Certificate for securing communications
keychain_sign
(macOS only): Binary to use identities in the macOS keychain for signing
Downloading
Download the signing service zip file from https://bitbucket.org/twocanoes/signing-manager/downloads/ that is the same build number as the client you are deploying. The zip file contains 3 folders: macOS, Windows, and Linux. Each folder contains the platform specific binary and a sample configuration file.
Generate Self Signed SSL Certificate (optional)
In order to secure communications between the clients and the signing server, an SSL certificate is required. If you are not able to obtain an SSL certificate from a trust authority, a self signed SSL certificate can be used. To generate a self signed certificate, open Terminal in macOS and run this command:
openssl req -newkey rsa:2048 -nodes -keyout server.key -x509 -days 365 -out server.pem
You will be prompted for information about the certificate. All values except for Common Name can be left blank. For Common Name, enter the computer name of computer that will be hosting the signing service with an extension of .local
. For example:
signingservice.local
Copy the server.pem
and the server.key
to the platform-specific folder you downloaded in the prior step.
Edit Settings
Edit the settings.json
in the platform-specific folder with a text editor and update the sections as outlined below.
settings.json
Format
The settings.json
file has 3 top level elements:
api_keys
: (Dictionary) Each dictionary key is an API key. The corresponding dictionary value for each is a text descriptor of that API key.identities
: (Array of dictionaries) Each dictionary has 3 keys:cn
,certificate
, andkey
.cn
is the subject name of a certificate.certificate
key is the certificate in PEM format.key
is the unencrypted private key in PEM format.keychain_identity_fingerprints
(optional) : (Array of dictionaries) Each dictionary must have a key calledsha1_hash
with a value that is a SHA1 hash (or fingerprint) of an identity in the macOS keychain. This key is only applicable if the signing service is running on macOS. If this key is defined and the service is started with the keychain option enabled (-k
), then theidentities
element is not used and all signing operations are done with the macOS keychain of the Mac upon which the signing service is running.
Both the identities
and keychain_identity_fingerprints
dictionaries optionally can have an additional key called api_keys
that can be used to restrict access to some identities to a subset of API keys. The api_keys
should be defined as an array of API keys. Any identity that does not define api_keys
will be available to a valid request using any of the API keys defined on the top-level of settings.json
.
API Keys
The API keys can be any unique string. It is recommended to use a UUID to guarantee that the API key is unique. A UUID can be generated by running uuidgen
in Terminal on macOS.
Identities
The identities arrays consists of a dictionary with 3 keys. To populate this dictionary from an identity in the macOS keychain, follow these steps:
- Open the macOS keychain that contains the macOS signing identity. Select the identity and choose File->Export Items...
- Save the exported identity as "SigningManagerID.p12". Make sure that the format to export is P12.
- Keychain Access will prompt for a passphrase to encrypt the P12. Create a P12 passphrase and enter it when prompted.
- Keychain Access will then prompt for the login password to export the identity. Enter the login password when prompted.
-
Windows and Linux installations require the identity to be put in the
settings.json
file. For macOS, the identities must be imported into the keychain on the signing service computer.For Windows and Linux:
The P12 must now be converted to an unencrypted PEM file. Enter the following command in macOS Terminal to convert the P12 to a PEM text file, removing the passphrase:
openssl pkcs12 -in SigningManagerID.p12 -out SigningManagerID.pem -nodes
Open the settings.json
file and populate certificate
, cn
and key
with the values in the exported pem file. Make sure to include the headers and footers of the certificate and private key (the lines that have BEGIN and END in them).
For macOS:
Install the exported identity to the keychain on the Mac that will run the signing service. In Keychain Access, open the certificate and copy the SHA-1 fingerprint of the certificate at the very bottom of the certificate. Add the fingerprint to the keychain_identity_fingerprints
array in the settings.json
file, removing all whitespace between the characters.
In Keychain Access, select the My Certificates
category and select the disclosure triangle next to the imported identity. Double click on the private key and select the Access Control
tab. Click +
and select keychain_binary
in the macOS folder of the signing service. This gives access to "keychain_binary" to do signing operations without prompting for a password.
The service is now ready to be started. Open the command line interface and change to the directory that has the signing service binary and run the command below. If you are not using an SSL certificate to secure the signing service, do not use the -s
flag. If a network port besides 3000 is required, specify it with the -p
option and provide the port as the argument (for example -p 3333
). If you want to use the macOS Keychain option add -k
and add keychain_identity_fingerprints
to settings.json
.
macOS and Linux:
nohup ./signing_service -s &
Note that if you get an error message on macOS Catalina or later about not being able to check the binary for malware, you can clear the quarantine flag by running:
xattr -d com.apple.quarantine signing_service
After clearing the flag, try starting the service again.
Windows:
signing_service.exe -s
A future release will provide a way to automatically start these services after reboot.
Testing
To verify the service is up and running, go a web browser on a different machine and enter the URL of the signing service. For instance, if the signing service is at 192.168.1.100, enter:
https://192.168.1.100:3000
If you are using a self-signed certificate, you may be prompted to allow the connection. Once you allow it, you should see a success message.
Client Configuration
Now that the signing service is running and accepting network connections, you can configure the macOS clients for signing operations. Configuration can be done either in the Preferences of the Signing Manager app or on the command line.
App Preferences
Launch the Signing Manager in /Applications
. If there are no preferences specified, the preferences window will automatically be shown. If it is not shown, select Preferences from the Signing Manager menu.
In the Preferences window, provide the URL to the signing service and an API key from settings.json
. If you are using a self-signed certificate for the signing service, select the Trust Self Signed Certificates
checkbox.
Command Line
The preferences can be set using the command line. The command line tool is located in the application bundle. Run it with the -h
option to see the available options. Note that you must include the quotes due to the spaces in the application name.
"/Applications/Signing Manager.app/Contents/MacOS/Signing Manager" -h -s Save settings. Requires -i and -a. Optionally use -d. -i <api host url> Specify host for API signing operations. -a <api_key> Specify api key for accessing signing service. -u trust self-signed certificates. -d debug logging -r refresh and display available certificates. -p print configuation. -h this message.
Using the -i
, -a
and -u
options, set the preferences. For example, with a host URL of https://signingserver.local:3000
, an API key of XYZ123
, and trusting self-signed certificates:
"/Applications/Signing Manager.app/Contents/MacOS/Signing Manager" -s -i https://signingserver.local:3000 -a XYZ123 -u
To verify the settings, use the -p
option:
"/Applications/Signing Manager.app/Contents/MacOS/Signing Manager" -p api_host: https://signingserver.local:3000 trust self signed: true debug: false API key: Set
Note that the API key is not shown, but can be found in the macOS keychain under com.twocanoes.signing-manager
.
Once the settings have been entered, click OK.
Using Signing Manager
Now that the signing service has been set up and the client is configured, applications and packages can now be signed. If no certificates are showing in the main interface of Signing Manager, click Refresh
on the toolbar.
To refresh available certificates on the command line, run:
"/Applications/Signing Manager.app/Contents/MacOS/Signing Manager" -r
A list of available certificates and the SHA-1 fingerprints will be shown.
Signing Apps
To sign an app, select a certificate in the main interface and click Copy codesign command
, then paste it into Terminal. Append the path to the application you want to sign and press return. For example:
codesign -fs "74FD9E670CFB7C906630B49FD26591CD66C66D79" ~/Documents/Projects/MyApp.app
Verify the signature by running codesign with the -dvvv
options:
codesign -dvvv ~/Documents/Projects/MyApp.app
Signing Packages
To sign an installer package, select a certificate in the main interface and click Copy productsign command
, then paste it into Terminal. Replace source.pkg
and destination.pkg
with a package to sign and a destination. For example:
productsign --sign "125F19515E25FA23CC1BA82E3E7A09D0A2097980" source.pkg destination.pkg
Verify the signature by double clicking on the signed package, then clicking on the certificate icon in the upper right corner of the first window of the installer.
Updated