Recent

Author Topic: CodeSign and Notarize procedures  (Read 564 times)

rossh_lz

  • New member
  • *
  • Posts: 5
CodeSign and Notarize procedures
« on: July 31, 2019, 03:34:22 pm »
Now Apple have added App Bundle notarizing, where they co-sign and validate the bundle.  From 10.14.x (Mojave) onwards, this is becoming enforced in various ways.


This procedure below applies to making and assembling your own app bundle, then placing it in a Package (.pkg) installer file, and then wrapping it all in a .dmg file for distribution.


The procedure I am using now is:


Setup:
1/  Join the Mac Dev Center through Appstore.  $119 a year - suck it up.
2/  In the Dev center, go to the certificate section, and create 2 new certificates:  Go to: Certificates ->  + to create new  There are now many choices.   Here I'm selecting "Developer ID Installer" and "Developer ID Application".   We use these when making app's that we sign and distribute ourselves.  You do this creating cert's in conjunction with KeyChain utility program and its Assistant and request a cert (use the saved to disk method)
3/  Download those two certs and install into your KeyChain (click the cer file).
4/  Download the Intermediate certs - Look for the Intermediate certs and get the WWDR and Developer ID Intermediate cert.  You might already have these installed.  Install these to your KeyChain too.

Assemble your app bundle.   Described here:  https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html#//apple_ref/doc/uid/10000123i-CH101-SW1


Signing:
5/  Sign your .app bundle:
/usr/bin/codesign -f -o runtime --timestamp -s "Developer ID Application: My Software Corp." /path/to/my/app/bundle.app
(use your real devel ID name per the cert).

Note:  If you are using outside libraries, including linking to inbuilt 3rd party things like openssl through fcl-web package, then you may need to include entitlements - see below.


6/  Make your package file with your signed .app bundle above.   I still use the PackageMaker, but its days are almost over.  Instead try the pkgbuild and productbuild command line tools.

7/  Sign your .pkg file:
/usr/bin/productsign --sign "Developer ID Installer: MyCoName inc." /input/path/to/package.pkg  /OUTPUT/path/for/the/result.pkg
(use your real install ID name per the cert).

8/  Make your .dmg file as required.   I use the command line tool
hdiutil create -ov -scrub -srcfolder  /bundle_dir/  -volname dmgvolname  /OUTPUT/path/for/the/result.dmg


Notarizing:
9/  Upload the finished dmg file to Apple:
/usr/bin/xcrun altool --notarize-app --primary-bundle-id "com.software.myapp.random" -u "me@mysoftware.com" -p "my_password" -t osx -f /path/to/my/dmg/file.dmg

10/  wait.... check the progress with:
/usr/bin/xcrun altool --notarization-history 0 -u "me@mysoftware.com" -p "my_password"

11/  After the above step registers "Package Approved", have Apple staple notarized signature to the dmg file with
/usr/bin/xcrun stapler staple  /path/to/my/dmg/file.dmg

Done.

To verify, install the app and call
/usr/bin/spctl -a -v /Applications/my_installed_app.app
...which will return "Notarized" and "accepted" if all is OK.
Most important... test the app by putting it in the Applications directory.  It's treated differently by the OS (ATS/Gatekeeper) when in the "installed" location.


***************

Notes:
Step  9 requires you to have a new 2FA application sign in's. see:
https://support.apple.com/en-us/HT204397

Apples guide to notarizing:
https://developer.apple.com/documentation/security/notarizing_your_app_before_distribution/customizing_the_notarization_workflow?language=objc


Entitlements:
Using the codesign's "-o runtime" option, enables the "hardened runtime" on the binary, which is required for notarizing.  But it also limits variables passed into and the calling of .dylib files.   If the external libraries are signed and notarized by you or Apple, then entitlements are not needed.  The normal framework libraries are signed by Apple.  But many third party .dylib's are not fully signed/notarized, or signed by third party but not you, so an entitlement is required to allow proper variable passing / library loading.  For these you will need to add an entitlements file to the project and add it to the codesign'n process of the .app bundle, as follows.

Step 5 above becomes:
/usr/bin/codesign -f -o runtime --entitlements path/to/my/app.entitlements  --timestamp -s "Developer ID Application: My Software Corp." /path/to/my/app/bundle.app

The "app.entitlements" file does not ship with the bundle - it's for the code sign process only.  The app.entitlements file looks like this:

<?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.cs.allow-dyld-environment-variables</key>
   <true/>   
</dict>
</plist>

The above enables the "Allow DYLD Environment Variables", which is sufficient to use the openssl packages.  You might also need the "Disable Library Validation" (com.apple.security.cs.disable-library-validation).    All available options are listed here under "Hardened Runtime":
https://developer.apple.com/documentation/bundleresources/entitlements?language=objc



#Aug 30th, 2019 - procedure updated
« Last Edit: August 30, 2019, 03:44:04 pm by rossh_lz »

jwdietrich

  • Hero Member
  • *****
  • Posts: 1028
    • formatio reticularis
Re: CodeSign and Notarize procedures
« Reply #1 on: August 10, 2019, 06:57:15 am »
Thanks for providing this important information. Would you mind to update the corresponding wiki page?
function GetRandomNumber: integer; // xkcd.com
begin
  GetRandomNumber := 4; // chosen by fair dice roll. Guaranteed to be random.
end;

http://www.formatio-reticularis.de

Lazarus 2.0.2 | FPC 3.0.4 | PPC, Intel, ARM | macOS, Windows, Linux

ChrisR

  • Jr. Member
  • **
  • Posts: 82
Re: CodeSign and Notarize procedures
« Reply #2 on: August 24, 2019, 01:11:38 pm »
This is really useful. Do you or anyone else in this community know how to notarize command line executables?

trev

  • Full Member
  • ***
  • Posts: 185
Re: CodeSign and Notarize procedures
« Reply #3 on: August 26, 2019, 12:05:10 pm »
Regarding command line tools and notarizing, this is the response I received from the TSI I lodged with Apple:

Quote
I’m responding to your report of problems notarising your command-line tool.  You wrote:

> However, there is obviously no "primary-bundle-id" because there are
> no `.app` bundles.

The notarisation system does not currently use this bundle ID for much.  You can supply any value that’s meaningful to you, although I recommend that you choose a sensible bundle ID by combining a DNS name that you control and your product name (for example, `org.domain.great-cow-basic`).

Having said that, command-line tools /can/ support a bundle ID and I recommend that you apply the bundle to your command-line tool as follows:

* When you build your tool, embed an `Info.plist` containing your bundle ID in the executable using the `-sectcreate` option with the segment name being `__TEXT` / `__info_plist`.  To learn more about this, follow the instructions I’ve included at the end of this response.

* When you sign your tool, set the code signing identifier to this bundle ID via the `-i` option to `codesign`.

* When you notarise your tool, pass this bundle ID to the notarisation system via the `--primary-bundle-id` option.

Share and Enjoy
--
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
<http://www.apple.com/developer/>

---------------------------------------------------------------------------
The best way to learn how to give a command-line tool an `Info.plist` is to copy what Xcode does:
   
1. Create a dummy command-line tool project in Xcode.

2. Add an `Info.plist` file to the project.  If you’re not sure how to set this up, copy the file from a new, dummy Mac app project.

3. Configure it appropriately.  If your `Info.plist` file references build settings, make sure those settings are configured in your target.  Of specific note is the Product Bundle Identifier (`PRODUCT_BUNDLE_IDENTIFIER`) build setting.

4. Set the Info.plist File (`INFOPLIST_FILE`) and Create Info.plist Section in Binary (`CREATE_INFOPLIST_SECTION_IN_BINARY`) build settings.

5. Build the project.

6. Use `otool` to confirm that the section was created correctly.

$ otool -s __TEXT __info_plist -v Test715194488
Contents of (__TEXT,__info_plist) section
<?xml version="1.0" encoding="UTF-8"?>

<plist version="1.0">
<dict>
    …
    <key>CFBundleIdentifier</key>
    <string>com.example.apple-samplecode.Test715194488</string>
    …
</dict>
</plist>

7. Look at the build transcript to see how Xcode created it.
---------------------------------------------------------------------------

As the command line tool I have been distributing is the Great Cow BASIC compiler for macOS, generated by a combination of FreeBASIC and gcc, it was not immediately obvious to me how these instructions would resolve my issue and I haven't had time to look at it in any detail since.
o Lazarus v2.1.0 r61775, FPC v3.3.1 r42640, macOS 10.14.6 (with sup update), Xcode 10.3
o Lazarus v2.1.0 r61574, FPC v3.3.1 r42318, FreeBSD 12.0 (Parallels VM)
o Lazarus v2.1.0 r61574, FPC v3.0.4, Ubuntu 18.04 (Parallels VM)

Hansaplast

  • Hero Member
  • *****
  • Posts: 535
  • Tweaking4All.com
    • Tweaking4All
Re: CodeSign and Notarize procedures
« Reply #4 on: September 11, 2019, 03:29:11 pm »
Thanks rossh_lz!
Worked like a charm for notarizing my apps!  ;)