This set of scripts currently provides macOS signing and notarization tools for command-line binaries.
The macOS signing and notarization tools (macos_sign.sh and macos_notarize.sh) must be run on macOS.
Examples:
./macos_sign.sh --signing-password="${SIGNING_TOOLS_SIGNING_PASSWORD}" --cert-file=${CERTFILE} --cert-name="${CERTNAME}" --target-binary="${TARGET_BINARY}"
./macos_notarize.sh --app-specific-password=${APP_SPECIFIC_PASSWORD} --apple-id=${APPLE_ID} --primary-bundle-id=com.ddev.test-signing-tools --target-binary=${TARGET_BINARY} [ --team-id=<short-id> ]
The rest of this file explains the methods and resources for signing.
DDEV and other tools use this to do macOS signing and notarization.
Apple's ongoing initiatives at controlling what runs on their platforms took a new turn with macOS Catalina (10.15), with required app and command-line binary signing.
Notarization requires
- An Apple Developer Program organization membership from developer.apple.com
- Obtaining a signing cert from Apple.
- Signing the binary or app with a Developer ID Certificate (not a distribution cert)
- Notarization (uploading the binary to Apple for approval)
- Validating code signing
- Validating notarization
- An app-specific password created on your Apple account.
- You may need a new "Developer Relations Intermediate Certificate". From https://developer.apple.com/forums/thread/662300 :
Just download the certificate from here and install it. If it doesn't works have a look on https://developer.apple.com/support/expiration/
- Signing requires the one-time task of obtaining a doing a certificate request (and creating associated private key) and downloading the certificate. See docs.
- Open
Keychain Access
and go toCertificate Assistant -> Request a Certificate from a Certificate Authority
- Provide the
User Email Address
and aCommon Name
identifier and save to disk. - Sign in with organization owner credentials at developer.apple.com
- At "Certificates, Identiifiers & Profiles" click the
+
to create a new certificate. - Choose "Developer ID Application"
- Upload the CSR you created.
- Download the created certificate (it's a `.cer file).
- Open the downloaded cert in Keychain Access
- In "My Certificates" export the cert at a .p12 file (it absolutely must be a .p12 file)
- Export the new cert with a password and place it to be used in your CI process.
- Open
- The process requires that binaries be hardened and signed with the Developer ID certificate, so, for example, DDEV's Apple account on developer.apple.com might have a cert called 'Developer ID Application: Localdev Foundation (9HQ298V2BW)'. This cert can be used for signing multiple binaries or applications.
- Signing is done with the macOS tool
codesign
. For example,codesign --keychain buildagent -s 'Developer ID Application: Localdev Foundation (9HQ298V2BW)' --timestamp --options runtime .gotmp/bin/darwin_amd64/ddev
. The macos_sign.sh tool here just codifies that process.
Signature validation can be done with codesign -v
, for example, codesign -vv -d .gotmp/bin/darwin_amd64/ddev
.
Notarizing a binary means
- Uploading the signed binary to Apple for its approval
- Verifying that the process completes successfully and has no warnings
- Verifying from the build process (a link given at notarization completed) that there are no warnings. (When I first got notarization to work, it reported that the package was accepted, but there was a warning that it did not have a "Developer ID" certificate, and thus was not successful.)
- In the case of a .app or other types of artifact, "stapling" the approval to the artifact. In the case of a command-line binary it is not possible to staple the approval. Apple announcement specifies that stapling is for apps, installer packages, and kernel extensions. We can expect this to be added in the future for command-line binaries, but at this time there is no place in the binary architecture for anything to be stapled. The Apple notarizing article says
Although tickets are created for standalone binaries, it’s not currently possible to staple tickets to them.
The best technique I've found for validating succesful notarization was archichect, which validates the signing and also checks in with Apple to see if it's been notarized.
codesign --test-requirement="=notarized" --verify --verbose ddev
was suggested as an approach, but it doesn't seem to work on a binary that can't be stapled.
Signing and Notarizing are implemented in DDEV-Local's Makefile and make darwin_signed
there does the whole process using the tools from this repo.
- Apple regularly changes their developer agreements. Every time they do, you have to agree to the change before notarizing will work. You have to sign into your apple account and then visit appstoreconnect.apple.com to accept the agreement. (When trying to notarize, you'll get "Error: Unable to notarize app." and "Error: code 1048 (You must first sign the relevant contracts online. (1048))" from altool.)
- Basic Step-by-step Signing and Notarization Walkthrough
- Testing Notarization and Archichect validation tool
- Notarization Answer on Stack Overflow
- notarize-app script for CI notarization.
- Apple's general Notarizing article
- Apple's Customizing the Notarization Workflow article
- CI Signing technique (Stack Overflow)
- Signing without the popup password (for CI, same SO question)
- Apple's Code Signing docs
- Common Code Signing Errors
- If you're making changes, use
make test
to test them. You'll need these environment variables set- APPLE_ID (the apple username/email related to the APP_SPECIFIC_PASSWORD)
- APP_SPECIFIC_PASSWORD (Apple app specific password)
- SIGNING_TOOLS_SIGNING_PASSWORD (signing password for the provided certificate).
- Forked PRs will not run tests in this repo, because they could expose the APP_SPECIFIC_PASSWORD.