The purpose of this blog is to help web developers to jump into systems programming. So you can ask any questions; there are no dummy questions. I want this blog to be a discussion space for every programmer who lives this journey.


I’m working on enabling notarization for macOS applications within our cross-platform framework.

Apple recently added a new command for notarizing applications called notarytool , which is a replacement for atool.

Notarize your application with notarytool

The base command for notarizing your application is:

xcrun notarytool submit myapp.zip \
  --apple-id <your-email> \
  --team-id <id-of-your-developer-id-application> \
  --password <app-specific-password>

In my case, I spawn a command with posix_spawnp, and I don’t want to handle sensitive data like identifiers and passwords.

Hopefully the notarytool submit command offers a --keychain-profile option:

xcrun notarytool submit myapp.zip \
  --keychain-profile "PROFILE_NAME" \
  --team-id <id-of-your-developer-id-application>

This option lets the user store their credentials and use them later. We’ll now see how to store credentials thanks to notarytool.

Store credentials with notarytool

The notarytool CLI comes with a store-credentials command:

Save authentication credentials for the Apple notary service to the default login keychain.

xcrun notarytool store-credentials "PROFILE_NAME" \
  --apple-id <your-email> \
  --team-id <id-of-your-developer-id-application> \
  --password <app-specific-password>

Let’s add this store-credentials command in CircleCI:

Use it in CircleCI

We’ll assume that we stored our Apple id, team id, and app-specific password as environment variables:

- run:
    name: Add notarization identity
    command: |
        xcrun notarytool store-credentials "PROFILE_NAME" \
            --apple-id $MACOS_APPLE_ID \
            --team-id $MACOS_TEAM_ID \
            --password $APPLE_DEVELOPER_CERT_PASSWORD

If you use this job, you’ll probably run into this error:

This process stores your credentials securely in the Keychain. You reference these credentials later using a profile name.

Validating your credentials...
Success. Credentials validated.
Error: An error occurred while accessing the keychain. User interaction is not allowed.

Exited with code exit status 1

CircleCI received exit code 1

By default, notarytool will use the default keychain. However, the default keychain may not be accessible in non-interactive shells. We’ll add the --keychain flag to the command:

- run:
    name: Add notarization identity
    command: |
        xcrun notarytool store-credentials "PROFILE_NAME" \
            --apple-id $MACOS_APPLE_ID \
            --team-id $MACOS_TEAM_ID \
            --password $APPLE_DEVELOPER_CERT_PASSWORD
            --keychain /Library/Keychains/System.keychain

Now we got a Write permissions error:

This process stores your credentials securely in the Keychain. You reference these credentials later using a profile name.

Validating your credentials...
Success. Credentials validated.
Error: An error occurred while accessing the keychain. Write permissions error.

Exited with code exit status 1

Let’s add a sudo:

- run:
    name: Add notarization identity
    command: |
        sudo xcrun notarytool store-credentials "PROFILE_NAME" \
            --apple-id $MACOS_APPLE_ID \
            --team-id $MACOS_TEAM_ID \
            --password $APPLE_DEVELOPER_CERT_PASSWORD
            --keychain /Library/Keychains/System.keychain

Now it works! 🎉

Validating your credentials...
Success. Credentials validated.
Credentials saved to Keychain.
To use them, specify `--keychain-profile "AC_NOTARY" --keychain /Library/Keychains/System.keychain`