Das folgende Skript notarisiert macOS Apps, Packages und DMG-Dateien voll automatisch. Dabei wird die original Datei notarisiert – eine extra ZIP-Datei muß vorher nicht erstellt werden.

Bitte beachten: Bevor wir die App notarisieren können, muss Sie erfolgreich code-signiert werden. Das Skript zum Code-Signieren von macOS Apps gibt es hier.

Das Gleiche gilt für PKG- und DMG-Dateien. Bei DMGs müssen alle darin enthaltenen Apps oder PKGs ebenfalls signiert werden.

Doch nun zum Notarization Script:

#!/bin/bash -u
#
# notarize 1.0.1
#
# Notarize an macOS app bundles, DMGs and PKGs.
# This script works with the original bundle, not with a extra ZIP file.
# Submitting the bundle ID for a app bundle is optional.
# Based on code by rednoah.
#
# Changelog:
# 1.0.1:
# - Added automatic bundle id extraction from app bundles.
# 1.0.0:
# - Simplified command line parameters.
# - Added automatic ZIP file creation.
# - Fixed UUID extraction.
# - Stapler won't be called, if the package is invalid.
#
# CALL:
# notarize appFilePackage [bundleID]
#
# E.g.: 
# ./notarize myapp.app
# ./notarize myapp.pkg com.marketmix.mypkg
#
# (c)2020 Harald Schneider

USR="h_schneider@marketmix.com"
PWD="xxxx-xxxx-xxxx-xxxx-xxxx"

if [ "$#" -eq 1 ]; then
    BUNDLE_ID=$(mdls -name kMDItemCFBundleIdentifier -r "$1")
    if [ $BUNDLE_ID == "(null)" ]; then
        echo
        echo "ERROR: Could not extract the Bundle ID."
        echo "Please submit a valid Bundle ID in a 2nd parameter!"
        exit
    fi
    echo
    echo "Extracted Bundle ID is ${BUNDLE_ID}"
else 
    BUNDLE_ID="$2"
    echo
fi

BUNDLE_APP="$1"
BUNDLE_ZIP="${BUNDLE_ID}".zip

# Create temporary files
NOTARIZE_APP_LOG=$(mktemp -t notarize-app)
NOTARIZE_INFO_LOG=$(mktemp -t notarize-info)

# Delete temporary files on exit
function finish {
  rm "$NOTARIZE_APP_LOG" "$NOTARIZE_INFO_LOG" "$BUNDLE_ZIP"
}
trap finish EXIT

echo "Building ZIP Archive: ${BUNDLE_ZIP} ..."
ditto -ck --sequesterRsrc --keepParent "${BUNDLE_APP}" "${BUNDLE_ZIP}" 
echo "Submitting notarization request. This can take a while ...."

# Submit app for notarization
if xcrun altool --notarize-app --primary-bundle-id "$BUNDLE_ID" --username "$USR" --password "$PWD" -f "$BUNDLE_ZIP" > "$NOTARIZE_APP_LOG" 2>&1; then
    echo ---------------------------------------------------------
  cat "$NOTARIZE_APP_LOG"|awk NF
    echo ---------------------------------------------------------
  
    RequestUUID=$(awk -F ' = ' '/RequestUUID/ {print $2}' "$NOTARIZE_APP_LOG")
    echo "Extracted UUID is" $RequestUUID
    echo ---------------------------------------------------------

    echo "Waiting for the Apple Notarization Server:"
    echo "The status will be updated every 60 seconds ..."

    # Check status periodically
  while sleep 60 && date; do
      echo ---------------------------------------------------------
        echo "Notarization in progress ...."
  
    	# Check notarization status
    if xcrun altool --notarization-info "$RequestUUID" --username "$USR" --password "$PWD" > "$NOTARIZE_INFO_LOG" 2>&1; then
      
            RESPONSE=$(awk -F ': ' '/Status Message/ {print $2}' "$NOTARIZE_INFO_LOG")

            if [ "$RESPONSE" != "" ]; then
                echo ---------------------------------------------------------
                echo "The Apple Notarization Server said: ${RESPONSE}"
            fi

            # Check server response before starting Stapler
            if [ "$RESPONSE" == "Package Approved" ]; then
            
                echo ---------------------------------------------------------
                echo "Running stapler. This can take a while ...."
        
                # Once notarization is complete, run stapler and exit
                if ! grep -q "Status: in progress" "$NOTARIZE_INFO_LOG"; then
                    xcrun stapler staple "$BUNDLE_APP"
                    exit $?
                fi
            fi
    else
        	echo ---------------------------------------------------------
      cat "$NOTARIZE_INFO_LOG" 1>&2
      exit 1
    fi
  done
else
  echo ---------------------------------------------------------
    echo "Logged result:"
  cat "$NOTARIZE_APP_LOG" 1>&2
  exit 1
fi

 

In den Variablen USR und PWD werden die eigenen Daten hinterlegt. Bei PWD handelt es sich um das App Specific Password. Danach speichern wir das Script unter “notarize” und setzen das Executable Flag mit

chmod +x notarize

Gestartet wird das Ganze dann mit

notarize MyAPP.app com.marketmix.myapp

Im o.g. Beispiel ist MyApp.app der Name unseres App Bundles und com.marketmix.myapp der Bundle Identifier. Dieser muss natürlich mit dem tatsächlichen Bundle Identifier in der App übereinstimmen. Die Angabe des Bundle Identifiers ist bei App Bundles optional. Wird der Parameter weg gelassen, so extrahiert das Script die ID aus dem App Bundle.

Das Skript erstellt automatisch eine temporäre ZIP-Datei, sendet diese an den Apple Notarization Server und startet die Notarisierung. Danach prüft es alle 60 Sekunden den Fortschritt der Notarisierung. Wurde diese erfolgreich abgeschlossen, wird das erhaltene Ticket in die original Datei eingepflegt.

Wenn die Notarisierung geklappt, hat steht im Output

...
---------------------------------------------------------
The Apple Notarization Server said: Package Approved
---------------------------------------------------------
Running stapler. This can take a while ....
Processing: MyApp.app
The staple and validate action worked!

oder eine entsprechende Fehlermeldung.