Notarise macOS command line apps more quickly

It’s June once more, and time for Apple’s Worldwide Developers’ Conference (WWDC). This is a chance to learn about new functionality and, yes, discover initiatives announced at previous WWDCs that you completely missed the first time around. A case in point: Apple’s revamp of how apps are notarised at the command line, which was revealed at WWDC 21 but I only encountered this week.

I’ve posted about command line notarisation before as it’s a key part of my workflow for releasing macOS command line tools. Notarisation requires the presence of an Info.plist file within the app bundle, so with CLI software the trick is to embed the plist in the binary, which is an Xcode build setting. That done, you can then notarise the compiled CLI software from the command line.

I currently use Apple’s ageing altool to do this, but this week I learned that this has not only been deprecated, but we’re also supposed to stop using it altogether come Autumn 2023. Some way away from June 2022, of course, but why dilly-dally along the way? The successor to altool is notarytool, and this is what was introduced at WWDC 21. Scroll through the list of WWDC 21 videos too aggressively and you’ll very easily overshoot notarytool’s announcement, and it’s not like you’d go looking for it on the off-chance in the depths of Xcode’s file structure. But it’s worth a look because notarytool is a big improvement on its predecessor. Here’s how it works.

You call notarytool using xcrun — which, as always, saves you the bother of having to find it when it’s almost certainly not in your PATH — and pass as parameters the submit command, the path to the binary or package you want to notarise, and your Apple developer credentials. You can also include a new flag, --wait. Just six Ascii characters but a big change: this flag causes notarytool to block until you have a notarisation pass or fail, saving you from the need to extract the notarisation task ID and use it to poll for the process’ status.

This is what my existing notarisation shell scripts, written to automate the process, do. So I’ve been able to update them by stripping all that polling business out, replaced with --wait.

The ‘new’ notarisation tool also features a better way to protect your credentials. My altool-based script pulls my Apple ID two-factor authentication passphrase from the keychain and transmits it alongside my Apple ID to authenticate with Apple’s notarisation server. The more modern approach employed by notarytool is to pull credentials both from the keychain, where they’re stored as a ‘profile’.

In a rare moment of ‘let’s make this easy for people’, Apple has implemented profile setup in notarytool. Just call:

xcrun notarytool store-credentials <new_profile_name> \
  --apple-id <your_apple_id> \
  --team-id <your_team_id> \
  --password <your_2FA_password>

The password is an app-specific passcode you can set up at appleid.apple.com.

Then, when you call notarytool to notarise something, you just pass in your profile name:

xcrun notarytool submit /path/to/binary \
  --keychain-profile <profile_name> \
  --wait

I’m in the process of updating all my tools to use notarytool instead of altool. You can view the script for notarising command line tools in my GitHub repo.

The output from notarytool can be controlled: if you’d prefer JSON rather than regular textual output, just add -output-format json to the submit call. You might not process JSON in a shell script, but if you’re scripting using a language like Python or Node, that will make processing the response from notarytool much easier.

Then again, you might not use notarytool at all and instead leverage the new Notify REST API and use your script to talk to Apple’s servers directly. My workflow is not complex, so the Apple tool is sufficient for my needs, but the update has streamlined matters.

Specifically, time to notarisation is a lot shorter with notarytool. A side-effect if its limited use? Or is it able to access ‘privileged’ Apple infrastructure? Time saved from excess poll cycles, perhaps? Whatever, notarisation now just takes on average 30s rather than many minutes before. That’s a saving well worth the effort of reworking my scripts.