#!/bin/bash # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at https://mozilla.org/MPL/2.0/. # # Runs codesign commands to codesign a Firefox .app bundle and enable macOS # Hardened Runtime. Intended to be manually run by developers working on macOS # 10.14+ who want to enable Hardened Runtime for manual testing. This is # provided as a stop-gap until automated build tooling is available that signs # binaries with a certificate generated during builds (bug 1522409). This # script requires macOS 10.14 because Hardened Runtime is only available for # applications running on 10.14 despite support for the codesign "-o runtime" # option being available in 10.13.6 and newer. # # The script requires an identity string (-i option) from an Apple Developer # ID certificate. This can be found in the macOS KeyChain after configuring an # Apple Developer ID certificate. # # Example usage on macOS 10.14: # # $ ./mach build # $ ./mach build package # $ open # # $ ./security/mac/hardenedruntime/codesign.bash \ # -a ~/Nightly.app \ # -i \ # -b security/mac/hardenedruntime/browser.developer.entitlements.xml # -p security/mac/hardenedruntime/plugin-container.developer.entitlements.xml # $ open ~/Nightly.app # usage () { echo "Usage: $0 " echo " -a " echo " -i " echo " -b " echo " -p " echo " [-o ]" exit -1 } # Make sure we are running on macOS with the sw_vers command available. SWVERS=/usr/bin/sw_vers if [ ! -x ${SWVERS} ]; then echo "ERROR: macOS 10.14 or later is required" exit -1 fi # Require macOS 10.14 or newer. OSVERSION=`${SWVERS} -productVersion|sed -En 's/[0-9]+\.([0-9]+)\.[0-9]+/\1/p'`; if [ ${OSVERSION} \< 14 ]; then echo "ERROR: macOS 10.14 or later is required" exit -1 fi while getopts "a:i:b:o:p:" opt; do case ${opt} in a ) BUNDLE=$OPTARG ;; i ) IDENTITY=$OPTARG ;; b ) BROWSER_ENTITLEMENTS_FILE=$OPTARG ;; p ) PLUGINCONTAINER_ENTITLEMENTS_FILE=$OPTARG ;; o ) OUTPUT_DMG_FILE=$OPTARG ;; \? ) usage; exit -1 ;; esac done if [ -z "${BUNDLE}" ] || [ -z "${IDENTITY}" ] || [ -z "${PLUGINCONTAINER_ENTITLEMENTS_FILE}" ] || [ -z "${BROWSER_ENTITLEMENTS_FILE}" ]; then usage exit -1 fi if [ ! -d "${BUNDLE}" ]; then echo "Invalid bundle. Bundle should be a .app directory" usage exit -1 fi if [ ! -e "${PLUGINCONTAINER_ENTITLEMENTS_FILE}" ]; then echo "Invalid entitlements file" usage exit -1 fi if [ ! -e "${BROWSER_ENTITLEMENTS_FILE}" ]; then echo "Invalid entitlements file" usage exit -1 fi # DMG file output flag is optional if [ ! -z "${OUTPUT_DMG_FILE}" ] && [ -e "${OUTPUT_DMG_FILE}" ]; then echo "Output dmg file ${OUTPUT_DMG_FILE} exists. Please delete it first." usage exit -1 fi echo "-------------------------------------------------------------------------" echo "bundle: $BUNDLE" echo "identity: $IDENTITY" echo "browser entitlements file: $BROWSER_ENTITLEMENTS_FILE" echo "plugin-container entitlements file: $PLUGINCONTAINER_ENTITLEMENTS_FILE" echo "output dmg file (optional): $OUTPUT_DMG_FILE" echo "-------------------------------------------------------------------------" # Clear extended attributes which cause codesign to fail xattr -cr "${BUNDLE}" # Sign these binaries first. Signing of some binaries has an ordering # requirement where other binaries must be signed first. codesign --force -o runtime --verbose --sign "$IDENTITY" \ "${BUNDLE}/Contents/MacOS/XUL" \ "${BUNDLE}/Contents/MacOS/pingsender" \ "${BUNDLE}/Contents/MacOS/minidump-analyzer" \ "${BUNDLE}"/Contents/MacOS/*.dylib codesign --force -o runtime --verbose --sign "$IDENTITY" --deep \ "${BUNDLE}"/Contents/MacOS/crashreporter.app codesign --force -o runtime --verbose --sign "$IDENTITY" --deep \ "${BUNDLE}"/Contents/MacOS/updater.app # Sign firefox main exectuable codesign --force -o runtime --verbose --sign "$IDENTITY" --deep \ --entitlements ${BROWSER_ENTITLEMENTS_FILE} \ "${BUNDLE}"/Contents/MacOS/firefox-bin \ "${BUNDLE}"/Contents/MacOS/firefox # Sign gmp-clearkey files find "${BUNDLE}"/Contents/Resources/gmp-clearkey -type f -exec \ codesign --force -o runtime --verbose --sign "$IDENTITY" {} \; # Sign the main bundle codesign --force -o runtime --verbose --sign "$IDENTITY" \ --entitlements ${BROWSER_ENTITLEMENTS_FILE} "${BUNDLE}" # Sign the plugin-container bundle with deep codesign --force -o runtime --verbose --sign "$IDENTITY" --deep \ --entitlements ${PLUGINCONTAINER_ENTITLEMENTS_FILE} \ "${BUNDLE}"/Contents/MacOS/plugin-container.app # Validate codesign -vvv --deep --strict "${BUNDLE}" # Create a DMG if [ ! -z "${OUTPUT_DMG_FILE}" ]; then DISK_IMAGE_DIR=`mktemp -d` TEMP_FILE=`mktemp` TEMP_DMG=${TEMP_FILE}.dmg NAME=`basename "${BUNDLE}"` ditto "${BUNDLE}" "${DISK_IMAGE_DIR}/${NAME}" hdiutil create -size 400m -fs HFS+ \ -volname Firefox -srcfolder "${DISK_IMAGE_DIR}" "${TEMP_DMG}" hdiutil convert -format UDZO \ -o "${OUTPUT_DMG_FILE}" "${TEMP_DMG}" rm ${TEMP_FILE} rm ${TEMP_DMG} rm -rf "${DISK_IMAGE_DIR}" fi