sigh/lib/assets/resign.sh in fastlane_hotfix-2.165.1 vs sigh/lib/assets/resign.sh in fastlane_hotfix-2.187.0
- old
+ new
@@ -73,10 +73,15 @@
# 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
# Logging functions
log() {
# Make sure it returns 0 code even when verose mode is off (test 1)
@@ -344,11 +349,11 @@
fi
done
}
# Find the bundle identifier contained inside a provisioning profile
-function bundle_id_for_provison {
+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#*.}"
}
@@ -382,11 +387,11 @@
if [[ ! -e "$PROVISION" ]]; then
error "Provisioning profile '$PROVISION' file does not exist"
fi
- local BUNDLE_ID=$(bundle_id_for_provison "$PROVISION")
+ 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
@@ -432,11 +437,11 @@
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_provison "$NEW_PROVISION")
+ 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
@@ -578,11 +583,11 @@
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_provison "$REF_PROVISION")
+ 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"
@@ -634,10 +639,24 @@
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 identifer, 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"
@@ -652,24 +671,18 @@
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 list identifiers inconsistent with app-defined ones, must use App entitlements value
- "com.apple.developer.icloud-container-identifiers" \
# 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" \
- # PP list a single TeamID.* identifier and not app-defined ones, must use App entitlements value
- "com.apple.developer.pass-type-identifiers" \
# If actually used by the App, this value will be set in its entitlements
"com.apple.developer.siri" \
- # PP list identifiers inconsistent with app-defined ones, must use App entitlements value
- "com.apple.developer.ubiquity-container-identifiers" \
# 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
@@ -678,12 +691,10 @@
"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" \
- # PP list identifiers inconsistent with app-defined ones, must use App entitlements value
- "com.apple.developer.in-app-payments" \
# 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
@@ -692,44 +703,49 @@
"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" \
- # PP seem to list the same groups as the App, but use App entitlements value to be sure
- "com.apple.security.application-groups" \
# 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
- # 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')
-
# 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
@@ -738,42 +754,63 @@
"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" \
- "com.apple.developer.icloud-container-identifiers" \
+ "com.apple.developer.icloud-container-environment|ICLOUD_ENV" \
"com.apple.developer.icloud-services" \
- "com.apple.developer.in-app-payments" \
"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.pass-type-identifiers|TEAM_ID" \
"com.apple.developer.siri" \
- "com.apple.developer.ubiquity-container-identifiers" \
"com.apple.developer.ubiquity-kvstore-identifier|TEAM_ID" \
"com.apple.external-accessory.wireless-configuration" \
- "com.apple.security.application-groups" \
"inter-app-audio" \
- "keychain-access-groups|APP_ID")
+ "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 | /usr/bin/sed -e 's,.*<plist[^>]*>\(.*\)</plist>,\1,g')"
+ 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
- if [[ "$KEY" == "com.apple.developer.icloud-container-environment" ]]; then
+ 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
@@ -786,52 +823,35 @@
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
- ICLOUD_ENV="Production"
+ NEW_ICLOUD_ENV="Production"
else
- ICLOUD_ENV="Development"
+ NEW_ICLOUD_ENV="Development"
fi
- log "Overriding value for $KEY"
- log "Old value: $ENTITLEMENTS_VALUE"
- log "New value: $ICLOUD_ENV"
- ENTITLEMENTS_VALUE="$ICLOUD_ENV"
+ 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
- log "App entitlements value for key '$KEY':"
- log "$ENTITLEMENTS_VALUE"
-
# 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 's/\./\\\./g')
+ PLUTIL_KEY=$(echo "$KEY" | /usr/bin/sed -e 's/\./\\\./g')
plutil -insert "$PLUTIL_KEY" -xml "$ENTITLEMENTS_VALUE" "$PATCHED_ENTITLEMENTS"
-
- # 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 identifier prefix '$OLD_APP_ID' with new value '$NEW_APP_ID'"
- /usr/bin/sed -i .bak "s/$OLD_APP_ID/$NEW_APP_ID/g" "$PATCHED_ENTITLEMENTS"
- 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'"
- /usr/bin/sed -i .bak "s/$OLD_TEAM_ID/$NEW_TEAM_ID/g" "$PATCHED_ENTITLEMENTS"
- else
- continue
- fi
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_provison "$NEW_PROVISION")"
+ 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>