Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
fastlane/sigh/lib/assets/resign.sh
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
executable file
932 lines (826 sloc)
44.4 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# shellcheck disable=SC2155 | |
# Copyright (c) 2011 Float Mobile Learning | |
# http://www.floatlearning.com/ | |
# Extension Copyright (c) 2013 Weptun Gmbh | |
# http://www.weptun.de | |
# | |
# Extended by Ronan O Ciosoig January 2012 | |
# | |
# Extended by Patrick Blitz, April 2013 | |
# | |
# Extended by John Turnipseed and Matthew Nespor, November 2014 | |
# http://nanonation.net/ | |
# | |
# Extended by Nicolas Bachschmidt, October 2015 | |
# | |
# Permission is hereby granted, free of charge, to any person obtaining | |
# a copy of this software and associated documentation files (the "Software"), | |
# to deal in the Software without restriction, including without limitation | |
# the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
# and/or sell copies of the Software, and to permit persons to whom the | |
# Software is furnished to do so, subject to the following conditions: | |
# | |
# The above copyright notice and this permission notice shall be included | |
# in all copies or substantial portions of the Software. | |
# | |
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
# | |
# Please let us know about any improvements you make to this script! | |
# ./floatsign source "iPhone Distribution: Name" -p "path/to/profile" [-d "display name"] [-e entitlements] [-k keychain] [-b "BundleIdentifier"] outputIpa | |
# | |
# | |
# Modifed 26th January 2012 | |
# | |
# new features January 2012: | |
# 1. change the app display name | |
# | |
# new features April 2013 | |
# 1. specify the target bundleId on the command line | |
# 2. correctly handles entitlements for keychain-enabled resigning | |
# | |
# new features November 2014 | |
# 1. now re-signs embedded iOS frameworks, if present, prior to re-signing the application itself | |
# 2. extracts the team-identifier from provisioning profile and uses it to update previous entitlements | |
# 3. fixed bug in packaging if -e flag is used | |
# 4. renamed 'temp' directory and made it a variable so it can be easily modified | |
# 5. various code formatting and logging adjustments | |
# | |
# new features October 2015 | |
# 1. now re-signs nested applications and app extensions, if present, prior to re-signing the application itself | |
# 2. enables the -p option to be used more than once | |
# 3. ensures the provisioning profile's bundle-identifier matches the app's bundle identifier | |
# 4. extracts the entitlements from the provisioning profile | |
# 5. copy the entitlements as archived-expanded-entitlements.xcent inside the app bundle (because Xcode does too) | |
# | |
# new features November 2018 | |
# 1. only create the archived-expanded-entitlements.xcent file if the version of Xcode < 9.3 as Xcode 10 does not create it. | |
# | |
# new features January 2019 | |
# 1. fixed bug where the com.apple.icloud-container-environment entitlement was being assigned an incorrect value | |
# | |
# new features March 2019 | |
# 1. two more fixes for only creating the archived-expanded-entitlements.xcent file if the version of Xcode < 9.3 as Xcode 10 does not create it. | |
# | |
# new features June 2020 | |
# 1. enable (re)signing of OnDemandResources when ipa has been built for the appstore | |
# | |
# new features August 2020 | |
# 1. fixes usage for users with GNU-sed in their $PATH | |
# | |
# new features May 2021 | |
# 1. fix entitlements merging when changing team | |
# | |
# new features June 2021 | |
# 1. fix the way app entitlements are extracted | |
# | |
# new features October 2021 | |
# 1. change codesign signatue to use --generate-entitlement-der to include DER encoded entitlements | |
# Logging functions | |
log() { | |
# Make sure it returns 0 code even when verose mode is off (test 1) | |
# To use like [[ condition ]] && log "x" && something | |
if [[ -n "$VERBOSE" ]]; then echo -e "$@"; else test 1; fi | |
} | |
error() { | |
echo "$@" >&2 | |
exit 1 | |
} | |
warning() { | |
echo "$@" >&2 | |
} | |
function checkStatus { | |
# shellcheck disable=SC2181 | |
if [ $? -ne 0 ]; then | |
error "Encountered an error, aborting!" | |
fi | |
} | |
usage() { | |
echo -e "Usage: $(basename "$0") source identity -p|--provisioning provisioning" >&2 | |
echo -e "\t\t[-e|--entitlements entitlements]" >&2 | |
echo -e "\t\t[-k|--keychain keychain]" >&2 | |
echo -e "\t\t[-d|--display-name displayName]" >&2 | |
echo -e "\t\t[-n|--version-number version]" >&2 | |
echo -e "\t\t[--short-version shortVersion]" >&2 | |
echo -e "\t\t[--bundle-version bundleVersion]" >&2 | |
echo -e "\t\t[-b|--bundle-id bundleId]" >&2 | |
echo -e "\t\t[--use-app-entitlements]" >&2 | |
echo -e "\t\toutputIpa" >&2 | |
echo "Usage: $(basename "$0") -h|--help" >&2 | |
echo "Options:" >&2 | |
echo -e "\t-p, --provisioning provisioning\t\tProvisioning profile option, may be provided multiple times." >&2 | |
echo -e "\t\t\t\t\t\tYou can specify provisioning profile file name." >&2 | |
echo -e "\t\t\t\t\t\t\t-p xxx.mobileprovision" >&2 | |
echo "" >&2 | |
echo -e "\t\t\t\t\t\tAlternatively you may provide multiple provisioning profiles if the application contains" >&2 | |
echo -e "\t\t\t\t\t\tnested applications or app extensions, which need their own provisioning" >&2 | |
echo -e "\t\t\t\t\t\tprofile. You can do so by providing -p option multiple times specifying" >&2 | |
echo -e "\t\t\t\t\t\told bundle identifier and new provisioning profile for that bundle id joined with '='." >&2 | |
echo -e "\t\t\t\t\t\t\t-p com.main-app=main-app.mobileprovision" >&2 | |
echo -e "\t\t\t\t\t\t\t-p com.nested-app=nested-app.mobileprovision" >&2 | |
echo -e "\t\t\t\t\t\t\t-p com.nested-extension=nested-extension.mobileprovision" >&2 | |
echo "" >&2 | |
echo -e "\t-e, --entitlements entitlements\t\tSpecify entitlements file path for code signing." >&2 | |
echo -e "\t-k, --keychain keychain\t\t\tSpecify keychain for code signing." >&2 | |
echo -e "\t-d, --display-name displayName\t\tSpecify new display name." >&2 | |
echo -e "\t\t\t\t\t\t\tWarning: will apply for all nested apps and extensions." >&2 | |
echo -e "\t-n, --version-number version\t\tSpecify new version number." >&2 | |
echo -e "\t\t\t\t\t\t\tWill set CFBundleShortVersionString and CFBundleVersion values in Info.plist." >&2 | |
echo -e "\t\t\t\t\t\t\tWill apply for all nested apps and extensions." >&2 | |
echo -e "\t --short-version shortVersion\tSpecify new short version string (CFBundleShortVersionString)." >&2 | |
echo -e "\t\t\t\t\t\t\tWill apply for all nested apps and extensions." >&2 | |
echo -e "\t\t\t\t\t\t\tCan't use together with '-n, --version-number' option." >&2 | |
echo -e "\t --bundle-version bundleVersion\tSpecify new bundle version (CFBundleVersion) number." >&2 | |
echo -e "\t\t\t\t\t\t\tWill apply for all nested apps and extensions." >&2 | |
echo -e "\t\t\t\t\t\t\tCan't use together with '-n, --version-number' option." >&2 | |
echo -e "\t-b, --bundle-id bundleId\t\tSpecify new bundle identifier (CFBundleIdentifier)." >&2 | |
echo -e "\t\t\t\t\t\t\tWarning: will NOT apply for nested apps and extensions." >&2 | |
echo -e "\t --use-app-entitlements\t\tExtract app bundle codesigning entitlements and combine with entitlements from new provisionin profile." >&2 | |
echo -e "\t\t\t\t\t\t\tCan't use together with '-e, --entitlements' option." >&2 | |
echo -e "\t--keychain-path path\t\t\tSpecify the path to a keychain that /usr/bin/codesign should use." >&2 | |
echo -e "\t-v, --verbose\t\t\t\tVerbose output." >&2 | |
echo -e "\t-h, --help\t\t\t\tDisplay help message." >&2 | |
exit 2 | |
} | |
if [ $# -lt 3 ]; then | |
usage | |
fi | |
ORIGINAL_FILE="$1" | |
CERTIFICATE="$2" | |
ENTITLEMENTS= | |
BUNDLE_IDENTIFIER="" | |
DISPLAY_NAME="" | |
KEYCHAIN="" | |
VERSION_NUMBER="" | |
SHORT_VERSION= | |
BUNDLE_VERSION= | |
KEYCHAIN_PATH= | |
RAW_PROVISIONS=() | |
PROVISIONS_BY_ID=() | |
DEFAULT_PROVISION="" | |
TEMP_DIR="_floatsignTemp" | |
USE_APP_ENTITLEMENTS="" | |
XCODE_VERSION="$(xcodebuild -version | grep "Xcode" | /usr/bin/cut -f 2 -d ' ')" | |
# List of plist keys used for reference to and from nested apps and extensions | |
NESTED_APP_REFERENCE_KEYS=(":WKCompanionAppBundleIdentifier" ":NSExtension:NSExtensionAttributes:WKAppBundleIdentifier") | |
# options start index | |
shift 2 | |
# Parse args | |
while [ "$1" != "" ]; do | |
case $1 in | |
-p | --provisioning ) | |
shift | |
RAW_PROVISIONS+=("$1") | |
;; | |
-e | --entitlements ) | |
shift | |
ENTITLEMENTS="$1" | |
;; | |
-d | --display-name ) | |
shift | |
DISPLAY_NAME="$1" | |
;; | |
-b | --bundle-id ) | |
shift | |
BUNDLE_IDENTIFIER="$1" | |
;; | |
-k | --keychain ) | |
shift | |
KEYCHAIN="$1" | |
;; | |
-n | --version-number ) | |
shift | |
VERSION_NUMBER="$1" | |
;; | |
--short-version ) | |
shift | |
SHORT_VERSION="$1" | |
;; | |
--bundle-version ) | |
shift | |
BUNDLE_VERSION="$1" | |
;; | |
--use-app-entitlements ) | |
USE_APP_ENTITLEMENTS="YES" | |
;; | |
--keychain-path ) | |
shift | |
KEYCHAIN_PATH="$1" | |
;; | |
-v | --verbose ) | |
VERBOSE="--verbose" | |
;; | |
-h | --help ) | |
usage | |
;; | |
* ) | |
[[ -n "$NEW_FILE" ]] && error "Multiple output file names specified!" | |
[[ -z "$NEW_FILE" ]] && NEW_FILE="$1" | |
;; | |
esac | |
# Next arg | |
shift | |
done | |
KEYCHAIN_FLAG= | |
if [ -n "$KEYCHAIN_PATH" ]; then | |
KEYCHAIN_FLAG="--keychain $KEYCHAIN_PATH" | |
fi | |
# Log the options | |
for provision in "${RAW_PROVISIONS[@]}"; do | |
if [[ "$provision" =~ .+=.+ ]]; then | |
log "Specified provisioning profile: '${provision#*=}' for bundle identifier: '${provision%%=*}'" | |
else | |
log "Specified provisioning profile: '$provision'" | |
fi | |
done | |
log "Original file: '$ORIGINAL_FILE'" | |
log "Certificate: '$CERTIFICATE'" | |
[[ -n "${DISPLAY_NAME}" ]] && log "Specified display name: '$DISPLAY_NAME'" | |
[[ -n "${ENTITLEMENTS}" ]] && log "Specified signing entitlements: '$ENTITLEMENTS'" | |
[[ -n "${BUNDLE_IDENTIFIER}" ]] && log "Specified bundle identifier: '$BUNDLE_IDENTIFIER'" | |
[[ -n "${KEYCHAIN}" ]] && log "Specified keychain to use: '$KEYCHAIN'" | |
[[ -n "${VERSION_NUMBER}" ]] && log "Specified version number to use: '$VERSION_NUMBER'" | |
[[ -n "${SHORT_VERSION}" ]] && log "Specified short version to use: '$SHORT_VERSION'" | |
[[ -n "${BUNDLE_VERSION}" ]] && log "Specified bundle version to use: '$BUNDLE_VERSION'" | |
[[ -n "${KEYCHAIN_FLAG}" ]] && log "Specified keychain to use: '$KEYCHAIN_PATH'" | |
[[ -n "${NEW_FILE}" ]] && log "Output file name: '$NEW_FILE'" | |
[[ -n "${USE_APP_ENTITLEMENTS}" ]] && log "Extract app entitlements: YES" | |
# Check that version number option is not clashing with short or bundle version options | |
[[ -n "$VERSION_NUMBER" && (-n "$SHORT_VERSION" || -n "$BUNDLE_VERSION") ]] && error "versionNumber option cannot be used in combination with shortVersion or bundleVersion options" | |
# Check that --use-app-entitlements and -e, --entitlements are not used at the same time | |
[[ -n "${USE_APP_ENTITLEMENTS}" && -n ${ENTITLEMENTS} ]] && error "--use-app-entitlements option cannot be used in combination with -e, --entitlements option." | |
# Check output file name | |
if [ -z "$NEW_FILE" ]; then | |
error "Output file name required" | |
fi | |
if [[ "${#RAW_PROVISIONS[*]}" == "0" ]]; then | |
error "-p 'xxxx.mobileprovision' argument is required" | |
fi | |
# Check for and remove the temporary directory if it already exists | |
if [ -d "$TEMP_DIR" ]; then | |
log "Removing previous temporary directory: '$TEMP_DIR'" | |
rm -Rf "$TEMP_DIR" | |
fi | |
filename=$(basename "$ORIGINAL_FILE") | |
extension="${filename##*.}" | |
filename="${filename%.*}" | |
# Check if the supplied file is an ipa or an app file | |
if [ "${extension}" = "ipa" ]; then | |
# Unzip the old ipa quietly | |
unzip -q "$ORIGINAL_FILE" -d $TEMP_DIR | |
checkStatus | |
elif [ "${extension}" = "app" ]; then | |
# Copy the app file into an ipa-like structure | |
mkdir -p "$TEMP_DIR/Payload" | |
cp -Rf "${ORIGINAL_FILE}" "$TEMP_DIR/Payload/${filename}.app" | |
checkStatus | |
else | |
error "Error: Only can resign .app files and .ipa files." | |
fi | |
# check the keychain | |
if [ "${KEYCHAIN}" != "" ]; then | |
security list-keychains -s "$KEYCHAIN" | |
security unlock "$KEYCHAIN" | |
security default-keychain -s "$KEYCHAIN" | |
fi | |
# Set the app name | |
# In Payload directory may be another file except .app file, such as StoreKit folder. | |
# Search the first .app file within the Payload directory | |
# shellcheck disable=SC2010 | |
APP_NAME=$(ls "$TEMP_DIR/Payload/" | grep ".app$" | head -1) | |
# Make sure that PATH includes the location of the PlistBuddy helper tool as its location is not standard | |
export PATH=$PATH:/usr/libexec | |
# Test whether two bundle identifiers match | |
# The first one may contain the wildcard character '*', in which case pattern matching will be used unless the third parameter is "STRICT" | |
function does_bundle_id_match { | |
# shellcheck disable=SC2049 | |
if [[ "$1" == "$2" ]]; then | |
return 0 | |
elif [[ "$3" != STRICT && "$1" =~ \* ]]; then | |
local PATTERN0="${1//\./\\.}" # com.example.* -> com\.example\.* | |
local PATTERN1="${PATTERN0//\*/.*}" # com\.example\.* -> com\.example\..* | |
if [[ "$2" =~ ^$PATTERN1$ ]]; then | |
return 0 | |
fi | |
fi | |
return 1 | |
} | |
# Find the provisioning profile for a given bundle identifier | |
function provision_for_bundle_id { | |
for ARG in "${PROVISIONS_BY_ID[@]}"; do | |
if does_bundle_id_match "${ARG%%=*}" "$1" "$2"; then | |
echo "${ARG#*=}" | |
break | |
fi | |
done | |
} | |
# Find the bundle identifier contained inside a provisioning profile | |
function bundle_id_for_provision { | |
local FULL_BUNDLE_ID=$(PlistBuddy -c 'Print :Entitlements:application-identifier' /dev/stdin <<< "$(security cms -D -i "$1")") | |
checkStatus | |
echo "${FULL_BUNDLE_ID#*.}" | |
} | |
# Add given provisioning profile and bundle identifier to the search list | |
function add_provision_for_bundle_id { | |
local PROVISION="$1" | |
local BUNDLE_ID="$2" | |
local CURRENT_PROVISION=$(provision_for_bundle_id "$BUNDLE_ID" STRICT) | |
if [[ "$CURRENT_PROVISION" != "" && "$CURRENT_PROVISION" != "$PROVISION" ]]; then | |
error "Conflicting provisioning profiles '$PROVISION' and '$CURRENT_PROVISION' for bundle identifier '$BUNDLE_ID'." | |
fi | |
PROVISIONS_BY_ID+=("$BUNDLE_ID=$PROVISION") | |
} | |
# Add given provisioning profile to the search list | |
function add_provision { | |
local PROVISION="$1" | |
if [[ "$1" =~ .+=.+ ]]; then | |
PROVISION="${1#*=}" | |
add_provision_for_bundle_id "$PROVISION" "${1%%=*}" | |
elif [[ "$DEFAULT_PROVISION" == "" ]]; then | |
DEFAULT_PROVISION="$PROVISION" | |
fi | |
if [[ ! -e "$PROVISION" ]]; then | |
error "Provisioning profile '$PROVISION' file does not exist" | |
fi | |
local BUNDLE_ID=$(bundle_id_for_provision "$PROVISION") | |
add_provision_for_bundle_id "$PROVISION" "$BUNDLE_ID" | |
} | |
# Load bundle identifiers from provisioning profiles | |
for ARG in "${RAW_PROVISIONS[@]}"; do | |
add_provision "$ARG" | |
done | |
# Resign the given application | |
function resign { | |
local APP_PATH="$1" | |
local NESTED="$2" | |
local BUNDLE_IDENTIFIER="$BUNDLE_IDENTIFIER" | |
local NEW_PROVISION="$NEW_PROVISION" | |
local APP_IDENTIFIER_PREFIX="" | |
local TEAM_IDENTIFIER="" | |
if [[ "$NESTED" == NESTED ]]; then | |
# Ignore bundle identifier for nested applications | |
BUNDLE_IDENTIFIER="" | |
fi | |
# Make sure that the Info.plist file is where we expect it | |
if [ ! -e "$APP_PATH/Info.plist" ]; then | |
error "Expected file does not exist: '$APP_PATH/Info.plist'" | |
fi | |
# Make a copy of old Info.plist, it will come handy later to extract some old values | |
cp -f "$APP_PATH/Info.plist" "$TEMP_DIR/oldInfo.plist" | |
# Read in current values from the app | |
local CURRENT_NAME=$(PlistBuddy -c "Print :CFBundleDisplayName" "$APP_PATH/Info.plist") | |
local CURRENT_BUNDLE_IDENTIFIER=$(PlistBuddy -c "Print :CFBundleIdentifier" "$APP_PATH/Info.plist") | |
local NEW_PROVISION=$(provision_for_bundle_id "${BUNDLE_IDENTIFIER:-$CURRENT_BUNDLE_IDENTIFIER}") | |
if [[ "$NEW_PROVISION" == "" && "$NESTED" != NESTED ]]; then | |
NEW_PROVISION="$DEFAULT_PROVISION" | |
fi | |
if [[ "$NEW_PROVISION" == "" ]]; then | |
if [[ "$NESTED" == NESTED ]]; then | |
warning "No provisioning profile for nested application: '$APP_PATH' with bundle identifier '${BUNDLE_IDENTIFIER:-$CURRENT_BUNDLE_IDENTIFIER}'" | |
else | |
warning "No provisioning profile for application: '$APP_PATH' with bundle identifier '${BUNDLE_IDENTIFIER:-$CURRENT_BUNDLE_IDENTIFIER}'" | |
fi | |
error "Use the -p option (example: -p com.example.app=xxxx.mobileprovision)" | |
fi | |
local PROVISION_BUNDLE_IDENTIFIER=$(bundle_id_for_provision "$NEW_PROVISION") | |
# Use provisioning profile's bundle identifier | |
if [ "$BUNDLE_IDENTIFIER" == "" ]; then | |
# shellcheck disable=SC2049 | |
if [[ "$PROVISION_BUNDLE_IDENTIFIER" =~ \* ]]; then | |
log "Bundle Identifier contains a *, using the current bundle identifier" | |
BUNDLE_IDENTIFIER="$CURRENT_BUNDLE_IDENTIFIER" | |
else | |
BUNDLE_IDENTIFIER="$PROVISION_BUNDLE_IDENTIFIER" | |
fi | |
fi | |
if ! does_bundle_id_match "$PROVISION_BUNDLE_IDENTIFIER" "$BUNDLE_IDENTIFIER"; then | |
error "Bundle Identifier '$PROVISION_BUNDLE_IDENTIFIER' in provisioning profile '$NEW_PROVISION' does not match the Bundle Identifier '$BUNDLE_IDENTIFIER' for application '$APP_PATH'." | |
fi | |
log "Current bundle identifier is: '$CURRENT_BUNDLE_IDENTIFIER'" | |
log "New bundle identifier will be: '$BUNDLE_IDENTIFIER'" | |
# Update the CFBundleDisplayName property in the Info.plist if a new name has been provided | |
if [ "${DISPLAY_NAME}" != "" ]; then | |
if [ "${DISPLAY_NAME}" != "${CURRENT_NAME}" ]; then | |
log "Changing display name from '$CURRENT_NAME' to '$DISPLAY_NAME'" | |
PlistBuddy -c "Set :CFBundleDisplayName $DISPLAY_NAME" "$APP_PATH/Info.plist" | |
fi | |
fi | |
# Replace the embedded mobile provisioning profile | |
log "Validating the new provisioning profile: $NEW_PROVISION" | |
security cms -D -i "$NEW_PROVISION" > "$TEMP_DIR/profile.plist" | |
checkStatus | |
APP_IDENTIFIER_PREFIX=$(PlistBuddy -c "Print :Entitlements:application-identifier" "$TEMP_DIR/profile.plist" | grep -E '^[A-Z0-9]*' -o | tr -d '\n') | |
if [ "$APP_IDENTIFIER_PREFIX" == "" ]; | |
then | |
APP_IDENTIFIER_PREFIX=$(PlistBuddy -c "Print :ApplicationIdentifierPrefix:0" "$TEMP_DIR/profile.plist") | |
if [ "$APP_IDENTIFIER_PREFIX" == "" ]; then | |
error "Failed to extract any app identifier prefix from '$NEW_PROVISION'" | |
else | |
warning "WARNING: extracted an app identifier prefix '$APP_IDENTIFIER_PREFIX' from '$NEW_PROVISION', but it was not found in the profile's entitlements" | |
fi | |
else | |
log "Profile app identifier prefix is '$APP_IDENTIFIER_PREFIX'" | |
fi | |
# Set new app identifier prefix if such entry exists in plist file | |
PlistBuddy -c "Set :AppIdentifierPrefix $APP_IDENTIFIER_PREFIX." "$APP_PATH/Info.plist" 2>/dev/null | |
TEAM_IDENTIFIER=$(PlistBuddy -c "Print :Entitlements:com.apple.developer.team-identifier" "$TEMP_DIR/profile.plist" | tr -d '\n') | |
if [ "$TEAM_IDENTIFIER" == "" ]; then | |
TEAM_IDENTIFIER=$(PlistBuddy -c "Print :TeamIdentifier:0" "$TEMP_DIR/profile.plist") | |
if [ "$TEAM_IDENTIFIER" == "" ]; then | |
warning "Failed to extract team identifier from '$NEW_PROVISION', resigned ipa may fail on iOS 8 and higher" | |
else | |
warning "WARNING: extracted a team identifier '$TEAM_IDENTIFIER' from '$NEW_PROVISION', but it was not found in the profile's entitlements, resigned ipa may fail on iOS 8 and higher" | |
fi | |
else | |
log "Profile team identifier is '$TEAM_IDENTIFIER'" | |
fi | |
# Make a copy of old embedded provisioning profile for further use | |
cp -f "$APP_PATH/embedded.mobileprovision" "$TEMP_DIR/old-embedded.mobileprovision" | |
# Replace embedded provisioning profile with new file | |
cp -f "$NEW_PROVISION" "$APP_PATH/embedded.mobileprovision" | |
#if the current bundle identifier is different from the new one in the provisioning profile, then change it. | |
if [ "$CURRENT_BUNDLE_IDENTIFIER" != "$BUNDLE_IDENTIFIER" ]; then | |
log "Updating the bundle identifier from '$CURRENT_BUNDLE_IDENTIFIER' to '$BUNDLE_IDENTIFIER'" | |
PlistBuddy -c "Set :CFBundleIdentifier $BUNDLE_IDENTIFIER" "$APP_PATH/Info.plist" | |
checkStatus | |
fi | |
# Update the version number properties in the Info.plist if a version number has been provided | |
if [ "$VERSION_NUMBER" != "" ]; then | |
CURRENT_VERSION_NUMBER=$(PlistBuddy -c "Print :CFBundleVersion" "$APP_PATH/Info.plist") | |
if [ "$VERSION_NUMBER" != "$CURRENT_VERSION_NUMBER" ]; then | |
log "Updating the version from '$CURRENT_VERSION_NUMBER' to '$VERSION_NUMBER'" | |
PlistBuddy -c "Set :CFBundleVersion $VERSION_NUMBER" "$APP_PATH/Info.plist" | |
PlistBuddy -c "Set :CFBundleShortVersionString $VERSION_NUMBER" "$APP_PATH/Info.plist" | |
fi | |
fi | |
# Update short version string in the Info.plist if provided | |
if [[ -n "$SHORT_VERSION" ]]; then | |
CURRENT_VALUE="$(PlistBuddy -c "Print :CFBundleShortVersionString" "$APP_PATH/Info.plist")" | |
# Even if the old value is same - just update, less code, less debugging | |
log "Updating the short version string (CFBundleShortVersionString) from '$CURRENT_VALUE' to '$SHORT_VERSION'" | |
PlistBuddy -c "Set :CFBundleShortVersionString $SHORT_VERSION" "$APP_PATH/Info.plist" | |
fi | |
# Update bundle version in the Info.plist if provided | |
if [[ -n "$BUNDLE_VERSION" ]]; then | |
CURRENT_VALUE="$(PlistBuddy -c "Print :CFBundleVersion" "$APP_PATH/Info.plist")" | |
# Even if the old value is same - just update, less code, less debugging | |
log "Updating the bundle version (CFBundleVersion) from '$CURRENT_VALUE' to '$BUNDLE_VERSION'" | |
PlistBuddy -c "Set :CFBundleVersion $BUNDLE_VERSION" "$APP_PATH/Info.plist" | |
fi | |
# Check for and resign OnDemandResource folders | |
ODR_DIR="$(dirname "$APP_PATH")/OnDemandResources" | |
if [ -d "$ODR_DIR" ]; then | |
for assetpack in "$ODR_DIR"/* | |
do | |
if [[ "$assetpack" == *.assetpack ]]; then | |
rm -rf $assetpack/_CodeSignature | |
/usr/bin/codesign ${VERBOSE} --generate-entitlement-der ${KEYCHAIN_FLAG} -f -s "$CERTIFICATE" "$assetpack" | |
checkStatus | |
else | |
log "Ignoring non-assetpack: $assetpack" | |
fi | |
done | |
fi | |
# Check for and resign any embedded frameworks (new feature for iOS 8 and above apps) | |
FRAMEWORKS_DIR="$APP_PATH/Frameworks" | |
if [ -d "$FRAMEWORKS_DIR" ]; then | |
if [ "$TEAM_IDENTIFIER" == "" ]; then | |
error "ERROR: embedded frameworks detected, re-signing iOS 8 (or higher) applications wihout a team identifier in the certificate/profile does not work" | |
fi | |
log "Resigning embedded frameworks using certificate: '$CERTIFICATE'" | |
for framework in "$FRAMEWORKS_DIR"/* | |
do | |
if [[ "$framework" == *.framework || "$framework" == *.dylib ]]; then | |
log "Resigning '$framework'" | |
# Must not qote KEYCHAIN_FLAG because it needs to be unwrapped and passed to codesign with spaces | |
# shellcheck disable=SC2086 | |
/usr/bin/codesign ${VERBOSE} --generate-entitlement-der ${KEYCHAIN_FLAG} -f -s "$CERTIFICATE" "$framework" | |
checkStatus | |
else | |
log "Ignoring non-framework: $framework" | |
fi | |
done | |
fi | |
# Check for and update bundle identifiers for extensions and associated nested apps | |
log "Fixing nested app and extension references" | |
for key in "${NESTED_APP_REFERENCE_KEYS[@]}"; do | |
# Check if Info.plist has a reference to another app or extension | |
REF_BUNDLE_ID=$(PlistBuddy -c "Print ${key}" "$APP_PATH/Info.plist" 2>/dev/null) | |
if [ -n "$REF_BUNDLE_ID" ]; then | |
# Found a reference bundle id, now get the corresponding provisioning profile for this bundle id | |
REF_PROVISION=$(provision_for_bundle_id "$REF_BUNDLE_ID") | |
# Map to the new bundle id | |
NEW_REF_BUNDLE_ID=$(bundle_id_for_provision "$REF_PROVISION") | |
# Change if not the same and if doesn't contain wildcard | |
# shellcheck disable=SC2049 | |
if [[ "$REF_BUNDLE_ID" != "$NEW_REF_BUNDLE_ID" ]] && ! [[ "$NEW_REF_BUNDLE_ID" =~ \* ]]; then | |
log "Updating nested app or extension reference for ${key} key from ${REF_BUNDLE_ID} to ${NEW_REF_BUNDLE_ID}" | |
PlistBuddy -c "Set ${key} $NEW_REF_BUNDLE_ID" "$APP_PATH/Info.plist" | |
fi | |
fi | |
done | |
if [ "$ENTITLEMENTS" != "" ]; then | |
if [ -n "$APP_IDENTIFIER_PREFIX" ]; then | |
# sanity check the 'application-identifier' is present in the provided entitlements and matches the provisioning profile value | |
ENTITLEMENTS_APP_ID_PREFIX=$(PlistBuddy -c "Print :application-identifier" "$ENTITLEMENTS" | grep -E '^[A-Z0-9]*' -o | tr -d '\n') | |
if [ "$ENTITLEMENTS_APP_ID_PREFIX" == "" ]; then | |
error "Provided entitlements file is missing a value for the required 'application-identifier' key" | |
elif [ "$ENTITLEMENTS_APP_ID_PREFIX" != "$APP_IDENTIFIER_PREFIX" ]; then | |
error "Provided entitlements file's app identifier prefix value '$ENTITLEMENTS_APP_ID_PREFIX' does not match the provided provisioning profile's value '$APP_IDENTIFIER_PREFIX'" | |
fi | |
fi | |
if [ -n "$TEAM_IDENTIFIER" ]; then | |
# sanity check the 'com.apple.developer.team-identifier' is present in the provided entitlements and matches the provisioning profile value | |
ENTITLEMENTS_TEAM_IDENTIFIER=$(PlistBuddy -c "Print :com.apple.developer.team-identifier" "$ENTITLEMENTS" | tr -d '\n') | |
if [ "$ENTITLEMENTS_TEAM_IDENTIFIER" == "" ]; then | |
error "Provided entitlements file is missing a value for the required 'com.apple.developer.team-identifier' key" | |
elif [ "$ENTITLEMENTS_TEAM_IDENTIFIER" != "$TEAM_IDENTIFIER" ]; then | |
error "Provided entitlements file's 'com.apple.developer.team-identifier' '$ENTITLEMENTS_TEAM_IDENTIFIER' does not match the provided provisioning profile's value '$TEAM_IDENTIFIER'" | |
fi | |
fi | |
log "Resigning application using certificate: '$CERTIFICATE'" | |
log "and entitlements: $ENTITLEMENTS" | |
if [[ "${XCODE_VERSION/.*/}" -lt 10 ]]; then | |
log "Creating an archived-expanded-entitlements.xcent file for Xcode 9 builds or earlier" | |
cp -f "$ENTITLEMENTS" "$APP_PATH/archived-expanded-entitlements.xcent" | |
fi | |
/usr/bin/codesign ${VERBOSE} --generate-entitlement-der -f -s "$CERTIFICATE" --entitlements "$ENTITLEMENTS" "$APP_PATH" | |
checkStatus | |
elif [[ -n "${USE_APP_ENTITLEMENTS}" ]]; then | |
# Extract entitlements from provisioning profile and from the app binary | |
# then combine them together | |
log "Extracting entitlements from provisioning profile" | |
PROFILE_ENTITLEMENTS="$TEMP_DIR/profileEntitlements" | |
PlistBuddy -x -c "Print Entitlements" "$TEMP_DIR/profile.plist" > "$PROFILE_ENTITLEMENTS" | |
checkStatus | |
log "Extracting entitlements from the app" | |
APP_ENTITLEMENTS="$TEMP_DIR/appEntitlements" | |
/usr/bin/codesign -d --entitlements :"$APP_ENTITLEMENTS" "$APP_PATH" | |
checkStatus | |
log "\nApp entitlements for ${APP_PATH}:" | |
log "$(cat "$APP_ENTITLEMENTS")" | |
# Get the old and new app identifier (prefix) | |
APP_ID_KEY="application-identifier" | |
# Extract just the identifier from the value | |
# Use the fact that we are after some identifier, which is always at the start of the string | |
OLD_APP_ID=$(PlistBuddy -c "Print $APP_ID_KEY" "$APP_ENTITLEMENTS" | grep -E '^[A-Z0-9]*' -o | tr -d '\n') | |
NEW_APP_ID=$(PlistBuddy -c "Print $APP_ID_KEY" "$PROFILE_ENTITLEMENTS" | grep -E '^[A-Z0-9]*' -o | tr -d '\n') | |
# Get the old and the new team ID | |
# Old team ID is not part of app entitlements, have to get it from old embedded provisioning profile | |
security cms -D -i "$TEMP_DIR/old-embedded.mobileprovision" > "$TEMP_DIR/old-embedded-profile.plist" | |
OLD_TEAM_ID=$(PlistBuddy -c "Print :TeamIdentifier:0" "$TEMP_DIR/old-embedded-profile.plist") | |
# New team ID is part of profile entitlements | |
NEW_TEAM_ID=$(PlistBuddy -c "Print com.apple.developer.team-identifier" "$PROFILE_ENTITLEMENTS" | grep -E '^[A-Z0-9]*' -o | tr -d '\n') | |
log "Patching profile entitlements with values from app entitlements" | |
PATCHED_ENTITLEMENTS="$TEMP_DIR/patchedEntitlements" | |
# Start with using what comes in provisioning profile entitlements before patching | |
cp -f "$PROFILE_ENTITLEMENTS" "$PATCHED_ENTITLEMENTS" | |
log "Removing denylisted keys from patched profile" | |
# See https://github.com/facebook/buck/issues/798 and https://github.com/facebook/buck/pull/802/files | |
# Update in https://github.com/facebook/buck/commit/99c0fbc3ab5ecf04d186913374f660683deccdef | |
# Update in https://github.com/facebook/buck/commit/36db188da9f6acbb9df419dc1904315ab00c4e19 | |
# Buck changes referenced above are not self-explanatory and do not seem exhaustive or up-to-date | |
# Comments below explain the rules applied to each key in order to make realignment with future Xcode export logic easier | |
DENYLISTED_KEYS=(\ | |
# PP list identifiers inconsistent with app-defined ones and this key does not seem to appear in IPA entitlements, so ignore it | |
"com.apple.developer.icloud-container-development-container-identifiers" \ | |
# This key has an invalid generic value in PP (actual value is set by Xcode during export), see dedicated processing a few blocks below | |
"com.apple.developer.icloud-container-environment" \ | |
# PP enable all available services and not app-defined ones, must use App entitlements value | |
"com.apple.developer.icloud-services" \ | |
# Was already denylisted in previous version, but has someone ever seen this key in a PP? | |
"com.apple.developer.restricted-resource-mode" \ | |
# If actually used by the App, this value will be set in its entitlements | |
"com.apple.developer.nfc.readersession.formats" \ | |
# If actually used by the App, this value will be set in its entitlements | |
"com.apple.developer.siri" \ | |
# PP define a generic TeamID.* identifier and not the app-defined one, must use App entitlements value | |
"com.apple.developer.ubiquity-kvstore-identifier" \ | |
# If actually used by the App, this value will be set in its entitlements | |
"inter-app-audio" \ | |
# PP define a generic TeamID.* identifier and not the app-defined one, must use App entitlements value | |
"keychain-access-groups" \ | |
# If actually used by the App, this value will be set in its entitlements | |
"com.apple.developer.homekit" \ | |
# If actually used by the App, this value will be set in its entitlements | |
"com.apple.developer.healthkit" \ | |
# If actually used by the App, this value will be set in its entitlements | |
"com.apple.developer.healthkit.access" \ | |
# If actually used by the App, this value will be set in its entitlements | |
"com.apple.developer.networking.vpn.api" \ | |
# If actually used by the App, this value will be set in its entitlements | |
"com.apple.developer.networking.HotspotConfiguration" \ | |
# PP list all available extensions and not app-defined ones, must use App entitlements value | |
"com.apple.developer.networking.networkextension" \ | |
# If actually used by the App, this value will be set in its entitlements | |
"com.apple.developer.networking.multipath" \ | |
# PP enable all domains via a non-AppStore-compliant '*' value, must use App entitlements value | |
"com.apple.developer.associated-domains" \ | |
# If actually used by the App, this value will be set in its entitlements | |
"com.apple.developer.default-data-protection" \ | |
# Was already denylisted in previous version, seems to be an artifact from an old Xcode release | |
"com.apple.developer.maps" \ | |
# If actually used by the App, this value will be set in its entitlements | |
"com.apple.external-accessory.wireless-configuration" | |
) | |
# If we change team while resigning, we have no other choice than to use the following entitlements from the PP instead of the App | |
# because they are based on unique identifiers (defined in the developer portal) that can't be shared between teams | |
if [[ "$OLD_TEAM_ID" != "$NEW_TEAM_ID" ]]; then | |
warning "WARNING: Changing team while resigning" | |
warning "WARNING: Using these entitlements from the provisioning profile instead of the existing app:" | |
warning "WARNING: App Groups, Merchant IDs (Apple Pay In-App Payments), iCloud Containers, Pass Type IDs (Wallet)" | |
warning "WARNING: If these capabilities are enabled, make sure AppID and provisioning profile are properly configured" | |
# For Pass Types, PP only list a single TeamID.* identifier and not the potential restricted list defined in the existing App | |
# but we can't guess the new identifiers to be used, so this generic value is better than nothing and should be fine for most apps | |
warning "WARNING: Resigned app will allow all pass types from the new team, even if old app only allowed a restricted list" | |
else | |
DENYLISTED_KEYS+=(\ | |
"com.apple.security.application-groups" \ | |
"com.apple.developer.in-app-payments" \ | |
"com.apple.developer.ubiquity-container-identifiers" \ | |
"com.apple.developer.icloud-container-identifiers" \ | |
"com.apple.developer.pass-type-identifiers" \ | |
) | |
fi | |
# Denylisted keys must not be included into new profile, so remove them from patched profile | |
for KEY in "${DENYLISTED_KEYS[@]}"; do | |
log "Removing denylisted key: $KEY" | |
PlistBuddy -c "Delete $KEY" "$PATCHED_ENTITLEMENTS" 2>/dev/null | |
done | |
# List of rules for transferring entitlements from app to profile plist | |
# The format for each enty is "KEY[|ID_TYPE]" | |
# Where KEY is the plist key, e.g. "keychain-access-groups" | |
# and ID_TYPE is optional part separated by '|' that specifies what value to patch: | |
# TEAM_ID - patch the TeamIdentifierPrefix | |
# APP_ID - patch the AppIdentifierPrefix | |
# ICLOUD_ENV - patch the target iCloud Environment | |
# Patching means replacing old value from app entitlements with new value from provisioning profile | |
# For example, for KEY=keychain-access-groups the ID_TYPE=APP_ID | |
# Which means that old app ID prefix in keychain-access-groups will be replaced with new app ID prefix | |
# There can be only one ID_TYPE specified | |
# If entitlements use more than one ID type for single entitlement, then this way of resigning will not work | |
# instead an entitlements file must be provided explicitly | |
ENTITLEMENTS_TRANSFER_RULES=(\ | |
"com.apple.developer.associated-domains" \ | |
"com.apple.developer.default-data-protection" \ | |
"com.apple.developer.healthkit" \ | |
"com.apple.developer.healthkit.access" \ | |
"com.apple.developer.homekit" \ | |
"com.apple.developer.icloud-container-environment|ICLOUD_ENV" \ | |
"com.apple.developer.icloud-services" \ | |
"com.apple.developer.networking.HotspotConfiguration" \ | |
"com.apple.developer.networking.multipath" \ | |
"com.apple.developer.networking.networkextension" \ | |
"com.apple.developer.networking.vpn.api" \ | |
"com.apple.developer.nfc.readersession.formats" \ | |
"com.apple.developer.siri" \ | |
"com.apple.developer.ubiquity-kvstore-identifier|TEAM_ID" \ | |
"com.apple.external-accessory.wireless-configuration" \ | |
"inter-app-audio" \ | |
"keychain-access-groups|APP_ID" \ | |
) | |
# If we change team while resigning, we have no other choice than to use the following entitlements from the PP instead of the App | |
# because they are based on unique identifiers (defined in the developer portal) that can't be shared between teams | |
# If we don't change team while resigning, we should use the following entitlements from the existing App and not from the PP | |
if [[ "$OLD_TEAM_ID" == "$NEW_TEAM_ID" ]]; then | |
ENTITLEMENTS_TRANSFER_RULES+=(\ | |
"com.apple.security.application-groups" \ | |
"com.apple.developer.in-app-payments" \ | |
"com.apple.developer.ubiquity-container-identifiers" \ | |
"com.apple.developer.icloud-container-identifiers" \ | |
"com.apple.developer.pass-type-identifiers|TEAM_ID" \ | |
) | |
fi | |
# Loop over all the entitlement keys that need to be transferred from app entitlements | |
for RULE in "${ENTITLEMENTS_TRANSFER_RULES[@]}"; do | |
KEY=$(echo "$RULE" | cut -d'|' -f1) | |
ID_TYPE=$(echo "$RULE" | cut -d'|' -f2) | |
# Get the entry from app's entitlements | |
# Read it with PlistBuddy as XML, then strip the header and <plist></plist> part | |
ENTITLEMENTS_VALUE="$(PlistBuddy -x -c "Print $KEY" "$APP_ENTITLEMENTS" 2>/dev/null | tr -d '\n' | /usr/bin/sed -e 's,.*<plist[^>]*>\(.*\)</plist>,\1,g')" | |
if [[ -z "$ENTITLEMENTS_VALUE" ]]; then | |
log "No value for '$KEY'" | |
continue | |
fi | |
log "App entitlements value for key '$KEY':" | |
log "$ENTITLEMENTS_VALUE" | |
# Patch the ID value if specified | |
if [[ "$ID_TYPE" == "APP_ID" ]]; then | |
# Replace old value with new value in patched entitlements | |
log "Replacing old app ID '$OLD_APP_ID' with new app ID '$NEW_APP_ID'" | |
ENTITLEMENTS_VALUE=$(echo "$ENTITLEMENTS_VALUE" | /usr/bin/sed -e "s/$OLD_APP_ID/$NEW_APP_ID/g") | |
elif [[ "$ID_TYPE" == "TEAM_ID" ]]; then | |
# Replace old team identifier with new value | |
log "Replacing old team ID '$OLD_TEAM_ID' with new team ID '$NEW_TEAM_ID'" | |
ENTITLEMENTS_VALUE=$(echo "$ENTITLEMENTS_VALUE" | /usr/bin/sed -e "s/$OLD_TEAM_ID/$NEW_TEAM_ID/g") | |
elif [[ "$ID_TYPE" == "ICLOUD_ENV" ]]; then | |
# Add specific iCloud Environment key to patched entitlements | |
# This value is set by Xcode during export (manually selected for Development and AdHoc, automatically set to Production for Store) | |
# Would need an additional dedicated option to specify the iCloud environment to be used (Development or Production) | |
# For now, we assume Production is to be used when signing with a Distribution certificate, Development if not | |
local certificate_name=$CERTIFICATE | |
local sha1_pattern='[0-9A-F]{40}' | |
if [[ "$CERTIFICATE" =~ $sha1_pattern ]]; then | |
log "Certificate $CERTIFICATE matches a SHA1 pattern" | |
local certificate_matches="$( security find-identity -v -p codesigning | grep -m 1 "$CERTIFICATE" )" | |
if [ -n "$certificate_matches" ]; then | |
certificate_name="$(/usr/bin/sed -E s/[^\"]+\"\([^\"]+\)\".*/\\1/ <<< $certificate_matches )" | |
log "Certificate name: $certificate_name" | |
fi | |
fi | |
OLD_ICLOUD_ENV=$(echo "$ENTITLEMENTS_VALUE" | /usr/bin/sed -e 's,<string>\(.*\)</string>,\1,g') | |
if [[ "$certificate_name" =~ "Distribution:" ]]; then | |
NEW_ICLOUD_ENV="Production" | |
else | |
NEW_ICLOUD_ENV="Development" | |
fi | |
log "Replacing iCloud environment '$OLD_ICLOUD_ENV' with '$NEW_ICLOUD_ENV'" | |
ENTITLEMENTS_VALUE=$(echo "$ENTITLEMENTS_VALUE" | /usr/bin/sed -e "s/$OLD_ICLOUD_ENV/$NEW_ICLOUD_ENV/g") | |
fi | |
# Remove the entry for current key from profisioning profile entitlements (if exists) | |
PlistBuddy -c "Delete $KEY" "$PATCHED_ENTITLEMENTS" 2>/dev/null | |
# Add new entry to patched entitlements | |
# plutil needs dots in the key path to be escaped (e.g. com\.apple\.security\.application-groups) | |
# otherwise it interprets they key path as nested keys | |
# TODO: Should be able to replace with echo ${KEY//\./\\\\.} and remove shellcheck disable directive | |
# shellcheck disable=SC2001 | |
PLUTIL_KEY=$(echo "$KEY" | /usr/bin/sed -e 's/\./\\\./g') | |
plutil -insert "$PLUTIL_KEY" -xml "$ENTITLEMENTS_VALUE" "$PATCHED_ENTITLEMENTS" | |
done | |
# Replace old bundle ID with new bundle ID in patched entitlements | |
# Read old bundle ID from the old Info.plist which was saved for this purpose | |
OLD_BUNDLE_ID="$(PlistBuddy -c "Print :CFBundleIdentifier" "$TEMP_DIR/oldInfo.plist")" | |
NEW_BUNDLE_ID="$(bundle_id_for_provision "$NEW_PROVISION")" | |
log "Replacing old bundle ID '$OLD_BUNDLE_ID' with new bundle ID '$NEW_BUNDLE_ID' in patched entitlements" | |
# Note: ideally we'd match against the opening <string> tag too, but this isn't possible | |
# because $OLD_BUNDLE_ID and $NEW_BUNDLE_ID do not include the team ID prefix which is | |
# present in the entitlements file. | |
# e.g. <string>AB1GP98Q19.com.example.foo</string> | |
# vs | |
# com.example.foo | |
/usr/bin/sed -i .bak "s!${OLD_BUNDLE_ID}</string>!${NEW_BUNDLE_ID}</string>!g" "$PATCHED_ENTITLEMENTS" | |
log "Resigning application using certificate: '$CERTIFICATE'" | |
log "and patched entitlements:" | |
log "$(cat "$PATCHED_ENTITLEMENTS")" | |
if [[ "${XCODE_VERSION/.*/}" -lt 10 ]]; then | |
log "Creating an archived-expanded-entitlements.xcent file for Xcode 9 builds or earlier" | |
cp -f "$PATCHED_ENTITLEMENTS" "$APP_PATH/archived-expanded-entitlements.xcent" | |
fi | |
/usr/bin/codesign ${VERBOSE} --generate-entitlement-der -f -s "$CERTIFICATE" --entitlements "$PATCHED_ENTITLEMENTS" "$APP_PATH" | |
checkStatus | |
else | |
log "Extracting entitlements from provisioning profile" | |
PlistBuddy -x -c "Print Entitlements" "$TEMP_DIR/profile.plist" > "$TEMP_DIR/newEntitlements" | |
checkStatus | |
log "Resigning application using certificate: '$CERTIFICATE'" | |
log "and entitlements from provisioning profile: $NEW_PROVISION" | |
if [[ "${XCODE_VERSION/.*/}" -lt 10 ]]; then | |
log "Creating an archived-expanded-entitlements.xcent file for Xcode 9 builds or earlier" | |
cp -- "$TEMP_DIR/newEntitlements" "$APP_PATH/archived-expanded-entitlements.xcent" | |
fi | |
# Must not qote KEYCHAIN_FLAG because it needs to be unwrapped and passed to codesign with spaces | |
# shellcheck disable=SC2086 | |
/usr/bin/codesign ${VERBOSE} --generate-entitlement-der ${KEYCHAIN_FLAG} -f -s "$CERTIFICATE" --entitlements "$TEMP_DIR/newEntitlements" "$APP_PATH" | |
checkStatus | |
fi | |
# Remove the temporary files if they were created before generating ipa | |
rm -f "$TEMP_DIR/newEntitlements" | |
rm -f "$PROFILE_ENTITLEMENTS" | |
rm -f "$APP_ENTITLEMENTS" | |
rm -f "$PATCHED_ENTITLEMENTS" | |
rm -f "$PATCHED_ENTITLEMENTS.bak" | |
rm -f "$TEMP_DIR/old-embedded-profile.plist" | |
rm -f "$TEMP_DIR/profile.plist" | |
rm -f "$TEMP_DIR/old-embedded.mobileprovision" | |
rm -f "$TEMP_DIR/oldInfo.plist" | |
} | |
# Sign nested applications and app extensions | |
while IFS= read -d '' -r app; | |
do | |
log "Resigning nested application: '$app'" | |
resign "$app" NESTED | |
done < <(find "$TEMP_DIR/Payload/$APP_NAME" -d -mindepth 1 \( -name "*.app" -or -name "*.appex" \) -print0) | |
# Resign the application | |
resign "$TEMP_DIR/Payload/$APP_NAME" | |
# Repackage quietly | |
log "Repackaging as $NEW_FILE" | |
# Zip up the contents of the "$TEMP_DIR" folder | |
# Navigate to the temporary directory (sending the output to null) | |
# Zip all the contents, saving the zip file in the above directory | |
# Navigate back to the orignating directory (sending the output to null) | |
pushd "$TEMP_DIR" > /dev/null | |
# TODO: Fix shellcheck warning and remove directive | |
# shellcheck disable=SC2035 | |
zip -qry "../$TEMP_DIR.ipa" * | |
popd > /dev/null | |
# Move the resulting ipa to the target destination | |
mv "$TEMP_DIR.ipa" "$NEW_FILE" | |
# Remove the temp directory | |
rm -rf "$TEMP_DIR" | |
log "Process complete" |