V17r5 Mac Notarization using Miyako's Code

Hi All,

I’ve spent a good day or so trying to learn and understand how to manually get a merged application from build through notarization. I have read everything - multiple times! And I am still having problems. My goal is to (I think) get the app notarized on Catalina and then hopefully it will work backwards in OS 12.6 up through Catalina.

I was able to manually figure out how to to use various terminal commands. I do have my Apple Developer Credentials installed in keychains, etc.

Once at this point setup DMG_Canvas manages and uploads to Apple. But alas still have errors due to:

“The executable does not have the hardened runtime enabled.”

“The binary is not signed.”

“The signature does not include a secure timestamp.”

For various 4D related, my own plugin which I’ll have to revisit, etc.

Anyway, this is all tedious and I wonder if it’s worth it. So I think I’ll use Miyako’s "4d-utility-build-application” if I can get it working. The docs on GitHub showing how to use it don’t seem to match the examples in the code? For example I assume that “TEST” is the method I want to call (different from the example on GitHub). Where …

$identity:= BLD_Find_Identity

Works and $signingIdentity returns the correct identity.

Thereafter I am a bit lost. I’m sure I need to update other information but it’s not obvious to me except at the very last part of the code:

$params.primaryBundleId:=“com.4D.”+$versionID

$params.username:="keisuke.miyako@4d.com" //account

$params.password:="@keychain:altool" //location for app specific password

Clearly this must be updated with my own user name, bundle ID, password, etc.

Is there anything else?

Would anyone who is using “4d-utility-build-application” share with me the places that need to be updated for my specific application?

And does this do everything I need to upload so my client can download and install without issue?

Appreciate,

John…

If you already have your developer credentials in keychain items, my signing script should be pretty easy for you to adapt to your app. You’ll need to use PHP and 4D Internet Commands from v18. If you have any executable binaries in your Resources folder, you’ll need to add lines to sign those too.

#!/bin/bash

cd "${BASH_SOURCE%/*}" || exit
echo "current directory: `pwd`"

devID="Developer ID Application: Me, myself, & I (ABCD1234)"
appPath="./Travel.app"

filename=$(basename -- "$appPath")
appName="${filename%.*}"

if [[ -d $appPath ]]
then
  echo "signing $appPath"
  # clean up by removing file system extended attributes
  xattr -cr "$appPath"
  
  # set up $IFS for find to handle spaces
  OIFS="$IFS"
  IFS=$'\n'
  
  # sign items in directories codesign --deep doesn't handle
  entPath="./signing.entitlements"
  extraDirs=("Plugins" "SASL Plugins" "Native Components")
  for extraDir in ${extraDirs[@]}; do
    for item in $(find "${appPath}/Contents/${extraDir}" -depth \( -iname "*.bundle" -o -iname "*.plugin" -o -iname "*.dylib" \)); do
      echo "signing \"${item}\""
      codesign --force --deep --verbose --options=runtime --entitlements ${entPath} --sign "$devID" "${item}"
    done
  done
  IFS="$OIFS" # restore $IFS
  
  # php, the Updater app, and anything else missed above
  codesign --force --deep --verbose --options=runtime --entitlements ${entPath} --sign "$devID" "${appPath}/Contents/Resources/php/Mac/php-fcgi-4d"
  codesign --force --deep --verbose --options=runtime --entitlements ${entPath} --sign "$devID" "${appPath}/Contents/Resources/Updater/Updater.app"
  
  # and the base app
  entPath="./signing.entitlements"
  codesign --force --deep --verbose --options=runtime --entitlements ${entPath} --sign "$devID" "${appPath}"
  
  # check code-signing
  echo "checking signing"
  spctl -av "$appPath"
  codesign --verify -v "$appPath"
  
  # zip with versioned name
  version=$(/usr/libexec/PlistBuddy "${appPath}/Contents/Info.plist" -c 'Print CFBundleShortVersionString')
  zipName="./${appName}-${version}.app.zip"
  echo "zipping to ${zipName}"
  rm "$zipName"
  ditto -c -k --sequesterRsrc --keepParent "$appPath" "$zipName"
  
  echo "uploading for notarization"
  xc_output=$( \
    xcrun altool --notarize-app --primary-bundle-id "com.quevivadev.Travel.zip" \
      --username "jim@quevivadev.com" --password "@keychain:AC_PASSWORD_Travel" \
      --file $zipName \
  )
  echo "${xc_output}"
  echo "finished uploading, watch for result email"
  
  # get request UUID, in results in line, using bash regular expressions
  # RequestUUID = 19ac980c-5a07-4584-9b57-e705b2d946e3
  regex="RequestUUID = ([0-9a-z\-]+)"
  [[ $xc_output =~ $regex ]]
  request_uuid=${BASH_REMATCH[1]}

  echo "run the following command for request status:"
  echo "xcrun altool --notarization-info ${request_uuid} -u \"jim@quevivadev.com\" --password \"@keychain:AC_PASSWORD_Travel\""
  
fi

# xcrun altool --store-password-in-keychain-item "AC_PASSWORD_Travel" -u "jim@quevivadev.com" -p "the-password"
# xcrun stapler staple Travel.app

Here’s a sample entitlements file:

<?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.allow-dyld-environment-variables</key>
	<true/>
	<key>com.apple.security.cs.allow-jit</key>
	<true/>
	<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
	<true/>
	<key>com.apple.security.cs.debugger</key>
	<true/>
	<key>com.apple.security.cs.disable-executable-page-protection</key>
	<true/>
	<key>com.apple.security.cs.disable-library-validation</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.addressbook</key>
	<true/>
	<key>com.apple.security.personal-information.calendars</key>
	<true/>
	<key>com.apple.security.personal-information.location</key>
	<true/>
	<key>com.apple.security.personal-information.photos-library</key>
	<true/>
</dict>
</plist>

Hi Jim,

Thanks for the code. I’ve had mixed results and I have sent you a private email. After having DMG_Canvas (running on OS 10.15-Catalina) upload to Apple the app failed with 55 errors.

I am not using the PHP and 4D Internet Commands in the v17 app. I have removed the PHP component. But if needs be I will move from v18 to the v17 app.

Anyway, appreciate your help.

John…

The above relates to App specific passwords.

The basic steps are as follows:

  1. log in to appleid.apple.com
  2. go through 2-factor authentication
  3. scroll down to “security”
  4. click “generate password”
  5. enter any label (alphanumerical)
    Note: you can create up to 25 passwords, you can remove then by clicking “edit”. the label helps you locate the unneeded password here, since the password itself is not displayed

The objective is 2-fold:

  • to avoid hard-coding the password in your codesign script.
  • to not using your apple ID password, the “master key” to open any doors

You can register your app-specific password with Xocde

xcrun altool --store-password-in-keychain-item "altool" --username "keisuke.miyako@4d.com" --password "xxxx-xxxx-xxxx-xxxx"

if you open the Keychain app, you will find the name (“altool” in the example above). note that this name has no relations to the label you entered online.

if the name is “altool”, you can pass @keychain:altool instead of the literal password to xcrun altool.

c.f.

https://miyako.github.io/2019/06/17/notarization.html

1 Like

Hi Miyako,

Thank you!

I already have completed the “basic” steps and I know what my developer ID and app specific password is. They have all been validated in the keychain. The build app is comprehensive! I am running in Parallels Catalina (10.15) and have installed XCode. So all the parts are there.

I am assuming that “” is the correct method to start from. As I indicated “BLD_Find_Identity” does find the correct $signingIdentity.

But there must be other places in this method that I have to update. Like the very end where the code is:

“$params.primaryBundleId:=“com.4D.”+$versionID”

My bundleId is just com.eternity-software.Peregrine

It doesn’t have any version associated? So this through me

Not sure what this line is for:

“$params.file:=System folder(Desktop)+$versionID+Folder separator+$name+$extension”

Then this line is repeated:

“$params.primaryBundleId:=“com.4D.”+$versionID”

The other lines I understand and have been setup correctly?

Are there any other places in the code I need to update?

How does it know where my built app is (it’s in the Final Application folder next to the structure)?

I’m pretty sure I have everything set that I need to. Just the mechanics I’m failing to appreciate.

I hope that makes sense?

John…

The only place to change is the path to your app.

But, just to be sure, I have pushed my current copy to GitHub.

You don’t need the app bundle ID to run this code, The ID used here is just a notarisation reference number, it can be anything that makes sense to you, it just has to be unique (that is why I simply use a UUID).

Hi Miyako,

Thank you.

May I ask why the Read.me example is different then the calls in the TEST method?

The example in github shows $status:=codesign(…) Where not all the parameters are visible. Is that the preferred way? If so is there anyway we can see all the parameters passed into this method?

Again thanks for the updated upload.

Appreciate, as always,
John…

Hi Miyako,

OK I think I understand. I didn’t realize that the bundle ID could change (as it would with UUID’s). So I’ve been using the same bundleId.

Question please? In the TEST method is this line supposed to be the oath to the App?

$path:=“Macintosh HD:Applications:4D v17.4:252917:4D.app:”

It threw me because it was a 4D app. Which is probably because you needed an example application.

Thanks,
John…

Yes, that is the path. In this example, I am signing 4D itself, to avoid translocation.

For me, that is not the preferred way. A one-shot “deep, forced” codesign at the app level (the example in README) is a blunt tool, it may or may not work for v18. It will definitely not work for v17 or its R cousins.

The TEST method signs the app from the inside out, performing various workarounds for symbolic links, 4D for iOS stuff, PHP, plugins, components, JS/HTML files, and so on.

Hi Miyako,

Ok thanks. Confusion removed.

Appreciate,
John…

Hi Miyako,

Ahhh!

I think I understand. Might it have to do with downloading and installing, for example, 4D v17r5 on Catalina? I noticed 4D either crashes or doesn’t work right on Catalina.

Again appreciate,
John…

Hi Miyako,

I’ve copied the code into my app. But is that the best strategy? Or should I just run it from the Build app?

Tks,
John…