Omnis Technical Note TNGI0030 Sept 2019

Notarizing your Omnis application for macOS

for Omnis Studio 10.0.0.3 or above
by Andrei Augustin

Apple is working with developers to create a safer Mac user experience and with the public release of macOS 10.15 Catalina, software must be notarized by Apple for it to run without a malware warning and show a more streamlined Gatekeeper interface.

In this Tech Note, we will guide you through the process of notarizing your Omnis application for a successful deployment on macOS Catalina. Note that for an application to be accepted for notarization by Apple, it must have a time stamped signature with the hardened runtime flags set (these flags are available only in macOS 10.13.6 High Sierra and later) and must use Developer ID.

One of the first requirements we need to satisfy is Xcode 10 or later with the command line tools. XCode 10 also requires at least macOS 10.13.6 (High Sierra).
Newer versions of Xcode (10.2 or more recent) requires at least macOS 10.14.3 or later.

The following instructions will guide you on how to notarize a standard Omnis tree from the command line. If you require more information about signing an Omnis tree, please refer to the Chapter 1 of the Omnis Programming documentation at the Code Signed Omnis (macOS) section; available here: https://developer.omnis.net/onlinedocs/Programming/01omnistools.html#code-signed-omnis-macos

Entitlements property list

The entitlement property list is required so that Apple knows what entitlements your runtime will require.

Most executables in the Omnis tree are signed with the following entitlements property list:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.automation.apple-events</key>
    <true/>
    <key>com.apple.security.cs.disable-library-validation</key>
    <true/>
    <key>com.apple.security.cs.allow-dyld-environment-variables</key>
    <true/>
    <key>com.apple.security.device.audio-input</key>
    <true/>
    <key>com.apple.security.device.camera</key>
    <true/>
    <key>com.apple.security.personal-information.location</key>
    <true/>
    <key>com.apple.security.personal-information.addressbook</key>
    <true/>
    <key>com.apple.security.personal-information.calendars</key>
    <true/>
    <key>com.apple.security.personal-information.photos-library</key>
    <true/>
</dict>
</plist>

Executables that are used as a sub-process (such as oBrowser helper app and the Node.js server app) will require extra entitlements to allow them to be run:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.automation.apple-events</key>
    <true/>
    <key>com.apple.security.cs.disable-library-validation</key>
    <true/>
    <key>com.apple.security.cs.allow-dyld-environment-variables</key>
    <true/>
    <key>com.apple.security.device.audio-input</key>
    <true/>
    <key>com.apple.security.device.camera</key>
    <true/>
    <key>com.apple.security.personal-information.location</key>
    <true/>
    <key>com.apple.security.personal-information.addressbook</key>
    <true/>
    <key>com.apple.security.personal-information.calendars</key>
    <true/>
    <key>com.apple.security.personal-information.photos-library</key>
    <true/>
    <key>com.apple.security.cs.debugger</key>
    <true/>
    <key>com.apple.security.cs.disable-executable-page-protection</key>
    <true/>
</dict>
</plist>

Next we will execute some commands in our terminal, so please make sure you have your standard_entitlements.plist and the extended_entitlmenets.plist files!

Let’s start with the Chromium based oBrowser component (you can skip this part if you are notarizing Omnis Studio 10.0.0.x or earlier). The CEF (Chromium Embedded Framework) libraries used are signed with the hardened runtime flag using the standard entitlements:

codesign -f -o runtime --entitlements /Users/omnis/standard_entitlements.plist --timestamp --verbose -s "Developer ID Application: My Company Ltd (X9999XXXXX)” /Users/omnis/Omnis\ Studio\ Runtime\ 10.0.0.3.app/Contents/MacOS/xcomp/obrowser.u_xcomp/Contents/Frameworks/Chromium\ Embedded\ Framework.framework/Libraries/*

And next you should see the libraries being codesigned successfully:

/Users/omnis/Omnis Studio Runtime 10.0.0.3.app/Contents/MacOS/xcomp/obrowser.u_xcomp/Contents/Frameworks/Chromium Embedded Framework.framework/Libraries/libEGL.dylib: signed Mach-O thin (x86_64) [libEGL]
/Users/omnis/Omnis Studio Runtime 10.0.0.3.app/Contents/MacOS/xcomp/obrowser.u_xcomp/Contents/Frameworks/Chromium Embedded Framework.framework/Libraries/libGLESv2.dylib: signed Mach-O thin (x86_64) [libGLESv2]
/Users/omnis/Omnis Studio Runtime 10.0.0.3.app/Contents/MacOS/xcomp/obrowser.u_xcomp/Contents/Frameworks/Chromium Embedded Framework.framework/Libraries/libswiftshader_libEGL.dylib: signed Mach-O thin (x86_64) [libswiftshader_libEGL]
/Users/omnis/Omnis Studio Runtime 10.0.0.3.app/Contents/MacOS/xcomp/obrowser.u_xcomp/Contents/Frameworks/Chromium Embedded Framework.framework/Libraries/libswiftshader_libGLESv2.dylib: signed Mach-O thin (x86_64) [libswiftshader_libGLESv2]

The Node.js app (sub-process used in 10.0 and later) will be signed with the extended entitlements:

codesign -f -o runtime --entitlements /Users/omnis/extended_entitlements.plist --timestamp --verbose -s "Developer ID Application: My Company Ltd (X9999XXXXX)" /Users/omnis/Omnis\ Studio\ Runtime\ 10.0.0.3.app/Contents/Resources/remotedebug/node

And we should see the confirmation:

/Users/omnis/Omnis Studio Runtime 10.0.0.3.app/Contents/Resources/remotedebug/node: signed Mach-O thin (x86_64) [node]

Afterwards, we can sign the Omnis tree recursively (using --deep) with the standard entitlements:

codesign -f --deep -o runtime --entitlements /Users/omnis/standard_entitlements.plist --timestamp --verbose -s "Developer ID Application: My Company Ltd (X9999XXXXX)" /Users/omnis/Omnis\ Studio\ Runtime\ 10.0.0.3.app/

And we should get the confirmation:

/Users/omnis/Omnis Studio Runtime 10.0.0.3.app/: replacing existing signature
/Users/omnis/Omnis Studio Runtime 10.0.0.3.app/: signed app bundle with Mach-O thin (x86_64) [net.mycompany.MyAppName]

The oBrowser helper (sub-process used in 10.0.0.3 and later) is signed with the extra entitlements:

codesign -f -o runtime --entitlements /Users/omnis/extra_entitlements.plist --timestamp --verbose -s "Developer ID Application: My Company Ltd (X9999XXXXX)" /Users/omnis/Omnis\ Studio\ Runtime\ 10.0.0.3.app/Contents/MacOS/xcomp/obrowser.u_xcomp/Contents/Frameworks/obrowser\ Helper.app/

And the confirmation:

/Users/omnis/Omnis Studio Runtime 10.0.0.3.app/Contents/MacOS/xcomp/obrowser.u_xcomp/Contents/Frameworks/obrowser Helper.app/: replacing existing signature
/Users/omnis/Omnis Studio Runtime 10.0.0.3.app/Contents/MacOS/xcomp/obrowser.u_xcomp/Contents/Frameworks/obrowser Helper.app/: signed app bundle with Mach-O thin (x86_64) [net.omnis.cefhelper]

The oBrowser xcomp root is re-signed with the normal entitlements:

codesign -f -o runtime --entitlements /Users/omnis/standard_entitlements.plist --timestamp --verbose -s "Developer ID Application: My Company Ltd (X9999XXXXX)" /Users/omnis/Omnis\ Studio\ Runtime\ 10.0.0.3.app/Contents/MacOS/xcomp/obrowser.u_xcomp

Will return:

/Users/omnis/Omnis Studio Runtime 10.0.0.3.app/Contents/MacOS/xcomp/obrowser.u_xcomp: replacing existing signature
/Users/omnis/Omnis Studio Runtime 10.0.0.3.app/Contents/MacOS/xcomp/obrowser.u_xcomp: signed bundle with Mach-O thin (x86_64) [net.omnis.component]

Then the root is re-signed to re-seal its resources:

codesign -f -o runtime --entitlements /Users/omnis/standard_entitlements.plist --timestamp --verbose -s "Developer ID Application: My Company Ltd (X9999XXXXX)" /Users/omnis/Omnis\ Studio\ Runtime\ 10.0.0.3.app/
And if successful, your terminal should return:

/Users/omnis/Omnis Studio Runtime 10.0.0.3.app/: replacing existing signature
/Users/omnis/Omnis Studio Runtime 10.0.0.3.app/: signed app bundle with Mach-O thin (x86_64) [net.mycompany.MyAppName]

Note that generally if you re-sign a sub-component, then its parent will need to be re-signed in order to re-seal its resources.

In order to verify the signature, run the following:

codesign -vvv --deep --strict /Users/omnis/Omnis\ Studio\ Runtime\ 10.0.0.3.app

And after some time, you should see at the end:

...
...
/Users/omnis/Omnis Studio Runtime 10.0.0.3.app: valid on disk
/Users/omnis/Omnis Studio Runtime 10.0.0.3.app: satisfies its Designated Requirement

At this point you should test that your signed application can run correctly on 10.14.6 and later, as the runtime flags will now be applied.

If everything works fine, we can proceed with submitting the signed app to Apple for notarization.

Submitting your app for notarization

In order to submit your application for Notarization to Apple, you will need to pack it up in a disk image (e.g. using the hdiutil tool) or in a zip file. Note that if you zip your application, do not use the zip -r as this has a side-effect on the tree structure and breaks the notarization scan, instead use the ditto command:

ditto -c -k --sequesterRsrc --keepParent Omnis\ Studio\ Runtime\ 10.0.0.3.app/ "Omnis Studio Runtime 10.0.0.3.zip"

Next, we will be using Xcode 10’s Application Loader (command line tool) to submit our application for notarization.

If you have multiple versions of Xcode on your machine, please use the sudo -s xcode-select -s <Path to Xcode 10 app> command to select Xcode 10 or newer.

You will need to use your Apple ID with an application specific password in order to use the Application Loader to submit apps to Apple for notarization. If you need to create an application specific password, log into the Apple ID administration page (https://appleid.apple.com/#!&page=signin) and under the Security section, select Generate Password.

The password should then be added to your login keychain as a named item to avoid having to send the password as clear text. Open the KeyChain Access utility and select the login keychain. From here you can use the + button to add the password with a unique name e.g. AC_PASSWORD. The account name is your Apple ID.

Now, use the following command to submit a zipped application package to Apple for notarization:

xcrun altool --notarize-app --primary-bundle-id net.mycompany.MyAppName --file Omnis\ Studio\ Runtime\ 10.0.0.3.zip --username first.last@icloud.com --password @keychain:AC_PASSWORD

Where the primary-bundle-id is anything to uniquely identify the app, the username is your Apple ID and the password is the name of the KeyChain item storing your application’s password.

If everything went successfully, the altool command should return something along the lines of:

2019-06-27 15:01:39.060 altool[38264:413651] No errors uploading 'Omnis Studio Runtime 10.0.0.3.zip'.
RequestUUID = 079029a7-afcd-4e86-989f-9bb7a58d9e22

Apple will scan the uploaded zip/dmg to ensure it can be notarized and send an email to inform you of the submission’s success or failure.

If the notarization process fails, you will receive an email from Apple with the subject “Your Mac software was not notarized” and the email will contain a request identification ID which can be used to obtain a URL pointing to a log of the issues encountered.

From the terminal, you can issue the following command with your request identification ID, username and KeyChain password to check for notarization info:

xcrun altool --notarization-info 079029a7-afcd-4e86-989f-9bb7a58d9e22 --username first.last@icloud.com --password @keychain:AC_PASSWORD

Which in case of failure will return:

019-06-27 15:24:57.574 altool[39188:432130] No errors getting notarization info.
    RequestUUID: 079029a7-afcd-4e86-989f-9bb7a58d9e22
        Date: 2019-06-27 14:01:39 +0000
        Status: invalid
    LogFileURL: https://osxapps-ssl.itunes.apple.com/itunes-assets/ ............
    Status Code: 2
Status Message: Package Invalid

You can also copy the URL from what the command returned and paste it into Safari if you want to get more details about the issues.

Once the issues have been fixed, re-sign, re-verify and re-submit the app to Apple for notarization.

If the notarization process is successful, you will receive an email from Apple with the subject “You can now distribute your Mac software”. The next step from here would be to staple the original application package:

stapler staple /Users/omnis/Omnis\ Studio\ Runtime\ 10.0.0.3.app

Which should return:

Processing: /Users/omnis/Omnis Studio Runtime 10.0.0.3.app
The staple and validate action worked!

Note that the stapled version should be incorporated into a dmg/zip for distribution. When using a dmg, this will also need to be signed (runtime flags are not required):

codesign -f --timestamp --verbose -s "Developer ID Application: My Company Ltd (X9999XXXXX)" /Users/omnis/Omnis-Studio-Runtime-10.0.0.3.dmg

You can also test a dmg for notarization:

spctl -a -t open --context context:primary-signature -v /Users/omnis/Omnis-Studio-Runtime-10.0.0.3.dmg

Which should return:

/Users/omnis/Omnis-Studio-Runtime-10.0.0.3.dmg: accepted
source=Notarized Developer ID

The signature of the dmg can be tested too:

codesign -vvv --deep --strict /Users/omnis/Omnis-Studio-Runtime-10.0.0.3.dmg

Which should return:

/Users/omnis/Omnis-Studio-Runtime-10.0.0.3.dmg: valid on disk
/Users/omnis/Omnis-Studio-Runtime-10.0.0.3.dmg: satisfies its Designated Requirement

Now that your app is notarized, you can deploy it to macOS 10.15 Catalina without the malware warning, congratulations!

  

Search Omnis Developer

 

Hit enter to search

X