Skip to content

Instantly share code, notes, and snippets.

@baggers-br
Created August 9, 2023 13:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save baggers-br/58f103f375778176d36a8d1025138d6e to your computer and use it in GitHub Desktop.
Save baggers-br/58f103f375778176d36a8d1025138d6e to your computer and use it in GitHub Desktop.
Sign and notarize
#!/bin/bash
cd "$(dirname "$0")"
# ----- Handle inputs -----
POSITIONAL_ARGS=()
for i in "$@"; do
case $i in
--apple-id=*)
APPLE_ID="${i#*=}"
shift # past argument=value
;;
--team-id=*)
TEAM_ID="${i#*=}"
shift # past argument=value
;;
--product-name=*)
PRODUCT_NAME="${i#*=}"
shift # past argument=value
;;
--signing-cert-id=*)
SIGNING_CERT_ID="${i#*=}"
shift # past argument=value
;;
--cert-b64=*)
P12_BASE64="${i#*=}"
shift # past argument=value
;;
--cert-pass=*)
P12_PASSWORD="${i#*=}"
shift # past argument=value
;;
--app-specific-pass=*)
APP_SPECIFIC_PASSWORD="${i#*=}"
shift # past argument=value
;;
--entitlements-file=*)
ENTITLEMENTS_PATH="${i#*=}"
shift # past argument=value
;;
--temp-dir=*)
TEMP_DIR_PATH="${i#*=}"
shift # past argument=value
;;
-*|--*)
echo "Unknown option $1"
exit 1
;;
*)
POSITIONAL_ARGS+=("$1") # save positional arg
shift # past argument
;;
esac
done
set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters
# ----- VARS -----
WORKING_PATH=$1
APPLE_CERT_PATH="$TEMP_DIR_PATH/apple-dev-cert.cer"
APP_PATH="$WORKING_PATH/$PRODUCT_NAME.app"
NOTARIZE_ZIP_PATH="$WORKING_PATH/$PRODUCT_NAME.zip"
TEMP_CERT_PATH="$TEMP_DIR_PATH/signingCert.p12"
TEMP_NOTARY_RESULT_PATH="$TEMP_DIR_PATH/notaryResultTemp"
KEYCHAIN_PROFILE="AC_PASSWORD"
KEYCHAIN_PATH="$TEMP_DIR_PATH/app-signing.keychain-db"
KEYCHAIN_PASSWORD=$(uuidgen)
OUTPUT_ZIP_PATH="$WORKING_PATH/$PRODUCT_NAME.zip"
# ----- Sanity check working path -----
if [ ! -d "$APP_PATH" ]
then
echo "Directory $APP_PATH DOES NOT exists."
exit 4
fi
if [ ! -f "$ENTITLEMENTS_PATH" ]
then
echo "Entitlements not found at $ENTITLEMENTS_PATH"
exit 5
fi
# ----- Prepare -----
rm -f "$NOTARIZE_ZIP_PATH"
rm -f "$OUTPUT_ZIP_PATH"
# ----- Create certificate files from secrets base64 -----
echo "$P12_BASE64" | base64 --decode > "$TEMP_CERT_PATH"
# ----- Configure Keychain -----
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
# ----- Import developer id certificates on Keychain -----
security import "$TEMP_CERT_PATH" -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
security list-keychain -d user -s $KEYCHAIN_PATH
# ----- Import apple root certificates on Keychain -----
curl -o "$APPLE_CERT_PATH" "https://www.apple.com/certificateauthority/DeveloperIDG2CA.cer"
security import "$APPLE_CERT_PATH" -A -k $KEYCHAIN_PATH
# ----- Sign -----
codesign --deep --force --verify --verbose --timestamp --options runtime --entitlements "$ENTITLEMENTS_PATH" --sign "$SIGNING_CERT_ID" "$APP_PATH"
# ----- Notarization -----
ditto -c -k --sequesterRsrc --keepParent "$APP_PATH" "$NOTARIZE_ZIP_PATH"
xcrun notarytool store-credentials "$KEYCHAIN_PROFILE" --apple-id "$APPLE_ID" --team-id "$TEAM_ID" --password "$APP_SPECIFIC_PASSWORD" --keychain "${KEYCHAIN_PATH}"
xcrun notarytool submit "$NOTARIZE_ZIP_PATH" --keychain-profile "$KEYCHAIN_PROFILE" --keychain "${KEYCHAIN_PATH}" --wait | tee "$TEMP_NOTARY_RESULT_PATH"
submitid=$(pcre2grep -o1 "^\s*id: ([0-9a-z-]+)" "$TEMP_NOTARY_RESULT_PATH" | head -1)
status=$(pcre2grep -o1 "^\s*status: (\w+$)" "$TEMP_NOTARY_RESULT_PATH")
rm -f "$TEMP_NOTARY_RESULT_PATH"
xcrun notarytool log --keychain-profile "$KEYCHAIN_PROFILE" --keychain "${KEYCHAIN_PATH}" $submitid
if [[ "$status" != "Accepted" ]]; then
log "Notarizing failed!"
exit 2
fi
# ----- Staple -----
xcrun stapler staple "$APP_PATH"
if [[ $? != 0 ]]; then
log "Stapling failed!"
exit 3
fi
security delete-keychain $KEYCHAIN_PATH
ditto -c -k --sequesterRsrc --keepParent "$APP_PATH" "$OUTPUT_ZIP_PATH"
@baggers-br
Copy link
Author

Don't use this yet. I'm still testing it.
However once this comment is gone it means it at least worked for us.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment