(Skippable) Backstory:
I have an app that customers initially install by:
- Going to our website in a browser,
- downloading a (notarized) disk image,
- mounting it,
- opening the (Developer ID-signed) installer package therein, and
- following the prompts to completion.
Once installed, this app has a button you can click that will check for updates and possibly install them. When you click this button:
- Our app contacts an HTTPS API on our servers to see if there is an update
- If there is an update, the API responds with a download URL to the aforementioned notarized disk image, and the SHA-512 hash of the disk image
- Our app downloads the disk image, and verifies the SHA-512 hash of the download
- Our app mounts the DMG
- Our app uses
/usr/sbin/pkgutil --check-signature
(although I do hope to switch toSecStaticCodeCheckValidity()
in the future) to verify that
- the OS thinks that the installer package is properly signed, and also that
- the organization unit on the leaf certificate for the code signing key used to sign the installer is exactly equal to our Apple Team ID
- Our app uses
/usr/sbin/installer -package ... -volinfo
to verify that the installer package thinks it can install onto the host- Our app uses
/usr/sbin/installer -package ... -target /
to install the software updateFor 98%+ of our users, this update process works great. For a tiny portion of users, we're seeing that
hdiutil
reports that it failed to attach the disk image. For the even tinier portion of users from whom we have obtained debug logs, one of the errors we've seen is "not recognized"; however, I don't know if that's the most common error, due to the small sample size.Before I get much further, I think it's prudent to acknowledge that the above system we're using today is pushing a decade old now, and it's probably wise to verify the foundations.
So...
For a Developer-ID-signed macOS app that is distributed outside the Mac App Store using an installer package, what is the "best" container/packaging system for an automated system to obtain and consume the installer package with the goal of a user-initiated self-update? For example:
- Notarized disk image (and failures to attach the image need to be bug reports to Apple)
- Just the installer package (If I understand correctly, this is bad because it bypasses the automatic propagation (normally performed by macOS) of the DMG's notary ticket to the pkg, right?)
- Something else?
Secondly, what are some common developer mistakes to avoid? For example, these come to mind:
- When saving the DMG to disk, explicitly enable quarantine on the DMG, so that macOS runs appropriate security checks as intended (is this correct?)
- When running the installer package, do not use low-level tools (like
cp
) to copy the pkg out of the DMG, because macOS won't be able to automatically find the notary ticket when the pkg is installed (is this correct?) - Anything else?
Additional context:
- We currently support macOS 10.13+, but we will soon support only macOS 10.15+.
Thank you!