Wiki

Clone wiki

Signing 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:

  1. Double click on the disk image to mount it in Finder.
  2. 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:

  1. macOS app ("Signing Manager.app") installed in the /Applications folder
  2. CryptoTokenKit extension installed in the Signing Manager.app bundle
  3. 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:

  1. api_keys: (Dictionary) Each dictionary key is an API key. The corresponding dictionary value for each is a text descriptor of that API key.
  2. identities: (Array of dictionaries) Each dictionary has 3 keys: cn, certificate, and key. 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.
  3. keychain_identity_fingerprints (optional) : (Array of dictionaries) Each dictionary must have a key called sha1_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 the identities 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:

  1. Open the macOS keychain that contains the macOS signing identity. Select the identity and choose File->Export Items...
  2. Save the exported identity as "SigningManagerID.p12". Make sure that the format to export is P12.
  3. Keychain Access will prompt for a passphrase to encrypt the P12. Create a P12 passphrase and enter it when prompted.
  4. Keychain Access will then prompt for the login password to export the identity. Enter the login password when prompted.
  5. 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