Notarization and multiple embedded tools/bundles

My product is a System Pref Pane which contains multiple embedded apps/tools to do its job, including:

  • A background-only renderer.
  • An app to handle a Menu Status Item.
  • An app to check for updates since System Preferences might not be running.
  • A unix executable relaunch tool to handle loading into System Preferences during an update. This one seems impossible to staple a notarization to.

I also have an installer (.app) that simply copies the System Pref Pane into place (needed because of a code-signing bug that prevents direct distribution of the prefPane).


The structure for my DMG looks like:


Installer.app

- PrefPane (in the Installer.app Resources folder)

-- Renderer.app (in the PrefPane Resources folder)

-- MenuStatusItem.app (in the PrefPane Resources folder)

-- Updater.app (in the PrefPane Resources folder)

-- Relaunch Tool (unix executable) (in the PrefPane Resources folder)


I have a nice script in Xcode that packages all this together. With Notarization, will I now need to notarize each of these individually starting at the deepest point? That sounds like a total hassle since automating it is difficult with the delay/polling required at Apple.

Will just Notarizing the outter-most container be enough?


I'm looking for suggestions from others that have multiple executables in a single app package as to dealing with Notarization.

Replies

When dealing with containers, like disk images and installer packages, you should, in general, only need to notarise the outermost container. The notarisation system will look inside the nested containers to find all your code and include it in your ticket. You can then staple the outermost container and you’re done.

After notarising your

.dmg
, download the
LogFileURL
to see what the ticket actually covers. See this thread for an example.

Having said that, your bundle structure seems a bit off to me. The

Contents/Resources/
directory is not an appropriate place for nested code. My recommendation is that you reconfigure as follows:

Installer.app

  • PrefPane in
    Contents/PlugIns/
    • Renderer.app in
      Contents/MacOS/
    • MenuStatusItem.app in
      Contents/MacOS/
    • Updater.app in
      Contents/MacOS/
    • Relaunch Tool in
      Contents/MacOS/

This is inline with the rules outlined in the Nested Code section of Technote 2206 macOS Code Signing In Depth.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

I can certainly restructure the layout of the contents. I have only ever seen raw executables in Contents/MacOS/. Is it appropriate to put a .app in there, or should it be in Contents/Helpers? The Nested Code docs say "These places are expected to contain only code" and of course a .app contains more than just code as it has image resources etc.


Note that the Installer.app will only run once and it will launch the .prefPane bundle which will force the OS to open System Preferences and copy the .prefPane into the appropriate place (~/Library/PreferencePanes). For this reason does the .prefPane itself need to be notarized?


Note that the .prefPane also contains an embedded .saver (Screen Saver) module. I guess this would go in the .prefPane's Contents/PlugIns/?


Even the Sparkle framework puts Autoupdate.app in Sparkle.framework/Versions/A/Resources, but this might be unique to frameworks.

Is it appropriate to put a .app in there, or should it be in

Contents/Helpers/
?

Both will work. I prefer

Contents/MacOS/
because you can get to items there using
-[NSBundle URLForAuxiliaryExecutable:]
.

For this reason does the

.prefPane
itself need to be notarized?

Everything needs to be notarised! However, if you notarise the outermost app then the resulting ticket should cover all the code within that. It’s worthwhile checking that, as I explained in my previous post.

Note that the

.prefPane
also contains an embedded .saver (Screen Saver) module. I guess this would go in the
.prefPane
’s
Contents/PlugIns/
?

That makes sense to me.

Even the Sparkle framework puts

Autoupdate.app
in
Sparkle.framework/Versions/A/Resources
, but this might be unique to frameworks.

IMO that’s a bug in that frameork. Having said that, frameworks are tricky because there’s no

Contents/MacOS
directory, so you have to use
Contents/Helpers/
. Annoyingly,
-[NSBundle URLForAuxiliaryExecutable:]
doesn’t return sensible results for a framework )-:

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

"Everything needs to be notarised! However, if you notarise the outermost app then the resulting ticket should cover all the code within that. It’s worthwhile checking that, as I explained in my previous post."


Keep in mine that this is an installer so while everything within it might be in the ticket, once the Installer copies the prefPane from it's internal PlugIns folder into System Preferences, and the installer goes away, the prefPane bundle will still need to know it is Notarized. Therefore, does it need it's own ticket?

When you open your

.dmg
, the system checks its notarisation. If the resulting ticket covers the other parts of your product (which you can check via the
LogFileURL
I discussed above), the system remembers that for when, say, the user opens your preferences pane.

Of course the proof of this particular pudding is in the eating, so you should definitely test this:

  1. Start with a VM that’s restored from a ‘fresh’ snapshot, one that’s never seen your software before.

  2. Download your

    .dmg
    without opening it.
  3. Disable networking on the VM.

  4. Run through your installation process and check that everything works.

Do this on both 10.14.5 and the latest 10.15 beta.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

What is a good VM to run 10.14 and the 10.15 beta in?


I have a spare test machine that I normally use for this.