how to call builtin-productPackagingUtility in command line - ios

When you specify an entitlement and a code signing identity in build settings (Xcode 4.2.1), you have the following output when you build from Xcode:
ProcessProductPackaging "myAppName.entitlements" "/path/to/myAppName.xcent"
cd /path/to/myAppName/SourceCode
builtin-productPackagingUtility "/path/to/myAppName/SourceCode/myAppName.entitlements" -entitlements -format xml -o "/path/to/myAppName.xcent"
CodeSign "/path/to/Garfields Comic Boom 1.0.app"
cd /path/to/myAppName/SourceCode
setenv CODESIGN_ALLOCATE /Developer/usr/bin/codesign_allocate
/usr/bin/codesign --force --sign "myCertificate" --entitlements "/path/to/myAppName.xcent" "/path/to/myAppName.app"
I would like to sign my app folder at the end of the build, and not during the Xcode build.
My problem is I don't know how to generate the xcent file in the command line.
Question : How do you generate xcent files in command line? I did a find from the root, there is nothing called productPackagingUtility...

I would like to sign my app folder at the end of the build, not during the Xcode build.
IIRC recent versions of Xcode complain if you disable code signing for a device build.
The easiest way around this is to let Xcode sign it and then re-sign it later. Steps are approximately
Dump the original entitlements with codesign -d --entitlements=MyApp.xcent MyApp.app
If you're changing provisioning profiles, copy the new one to MyApp.app/embedded.mobileprovision and modify the entitlements accordingly (IIRC the file format has a 4-byte magic and a 4-byte length; remember to update the length!).
Re-sign with your desired certificate.

Using the codesign utility does not require an xcent file. You can simply create a plist file and use that for entitlements. Make sure it is an XML plist, not binary.

The format of the .entitlements and the ${APPNAME}.xcent is the same so it can just be copied across.

Related

Create .ipa using multiple targets

Currently I'm using a bash script to build and archive our iOS application. With the introduction of "Watch" I have found that my script is no longer able to create the necessary .ipa file as it once did.
The build would generate a single .app file which I would use XCRUN to invoke PackageApplication in order to create the .ipa. Now I'm looking to archive 2 .app files along with 1 .appex file.
Has anyone been able to successfully create an .ipa file via command line/script with multiple .app files?
Using Xcode 6.2
Update
Now using Xcode 7 GM along with OSX 10.10.4.
For "TEST" builds I had a difficult time with developers always changing the profiles so I made 2 builds; one from the command line and the other via the IDE (Xcode). I changed the .ipa extension to .zip and compared the 2.
The good build from the IDE had generated a file called "archived-expanded-entitlements.xcent" which had all the signing identities defined correctly.
I copied this file out to a different directory and use it to inject with all other subsequent builds. The builds now are able to be loaded on the phone & watch for testing.
Below is an example of how to do it. A bit of a hack but it works.
security -v unlock-keychain -p "password" "keychainPath"
xcodebuild -configuration Test -scheme YourAppName -archivePath somePath/YourAppName.xcarchive archive
xcodebuild -exportArchive -exportFormat IPA -archivePath somePath/YourAppName.xcarchive -exportPath somePath/YourAppName.ipa
unzip -o somePath/YourAppName.ipa -d somePath
cp somePath/archived-expanded-entitlements.xcent somePath/Payload/YourAppName.app
zip -qr somePath/YourAppName.ipa Payload
I find a solution which is working on the archive file of the project which has watch, app and extension.
xcodebuild -exportArchive -archivePath AppName.xcarchive/ -exportPath AppName.ipa -exportFormat ipa -exportWithOriginalSigningIdentity
This command basically uses same signing identify and provisioning profile to export the ipa from raw xcarchive file.
We have sort of work around to generate .ipa that contains iPhone app and apple watch app.
After the .app is generated using Xcodebuild, in the bash script we do the following
A)
Create Directory with Application Name
Inside Application directory create sub directory named Payload
Copy .app into Payload directory
B)
Inside Application directory create sub directory named WatchKitSupport as a sibling to Payload.
Copy a binary named "WK" from the iOS 8.2 SDK in Xcode to your new WatchKitSupport directory. This binary can be found at: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/Library/Application Support/WatchKit/
Make sure the "WK" binary is not touched/re-signed in any way. This is important for validation on device.
Zip the application folder
Rename .zip to .ipa
When expanded the IPA should contain (at least):
xxx.ipa
|________Payload/
|________WatchKitSupport/
|_____WK
This works for us.

Issue with building and signing an iOS app with a configurable bundle identifier to support multiple build configurations

I am trying to build multiple concurrent builds of my app (one for mocking environment, one for development environment, one for testing environment, one for production release).
I have gotten very far in getting this working, but am having issues with the codesigning of an app with a auto-generated bundle identifier (one running off a variable).
WHAT I HAVE DONE SO FAR
I am using xCode 4.6.3 using an adhoc provisioning profile.
To attempt to get this to work, I am setting my bundle identifier in the info plist file to somewhat running off a variable - so the app can be signed in different ways.
E.g. my actual bundle identifiers are:
UXXXXXX.au.com.blah.MOCK
UXXXXXX.au.com.blah.DEV
UXXXXXX.au.com.blah.TEST
UXXXXXX.au.com.blah.PROD
Therefore my bundle identifier in my info plist has been configured as "UXXXXXX.au.com.blah.${BUNDLE_SUFFIX}"
Now to allow me to build the app differently for each build, I did the following:
I have 4 different bundle identifiers with 4 different provisioning profiles assigned to those bundle identifiers
To begin with i added a new configuration called "MOCK" (I will add the others in later)
Then under the project build settings I added a BUNDLE_SUFFIX user defined variable to my project and set it to MOCK for the MOCK configuration (I will add the others in later). This is used to set the bundle identifier for a build that uses the MOCK configuration.
Then under the project build settings, selected my MOCK provisioning profile for the MOCK configuration in build settings
I notice if i go to the summary view on my app target it displays the bundle id as UXXXXXX.au.com.blah.MOCK with the 'MOCK' part being in grey font - so it has picked up the bundle suffix variable
Then i created a new scheme called MOCK to use MOCK configuration for 'Profile' and 'Archive'. I left defaults for the rest (uses DEBUG).
So now I can run an xcodebuild and use scheme MOCK to do a MOCK specific build that will use the MOCK configuration to set the bundle identifier to .MOCK and set my provisoning profile to use _MOCK profile.
So i then run a jenkins build which does an xcodebuild and xcrun (which will call codesign).
This is my xcodebuild command:
/usr/bin/xcodebuild -scheme MOCK -sdk iphoneos -project MyApp.xcodeproj -configuration MOCK clean build "CONFIGURATION_BUILD_DIR=/Users/CI/Documents/workspace/build3" ONLY_ACTIVE_ARCH=NO DEPLOY_ENVIRONMENT=MOCK "CODE_SIGN_IDENTITY=iPhone Distribution: My Company" "PROVISIONING_PROFILE=XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
This is my xcrun command:
/usr/bin/xcrun -sdk iphoneos PackageApplication -v "/Users/Shared/Jenkins/Home/jobs/MyApp.app" -o "/Users/Shared/Jenkins/Home/jobs/MyApp/workspace/build/MyApp-0.9.5.0.ipa" --embed "/Users/Shared/Jenkins/Home/Library/MobileDevice/Provisioning Profiles/20130816_Distribution_MOCK.mobileprovision" --sign "iPhone Distribution: My Company"
NOTE: I specifically sign the app with the MOCK provisioning profile, as I worked out that I cannot sign the app with a .* profile, as the app uses push notifications and if I build the app with a .* and then re-sign the app with the proper profile, my embedded.mobileprovision profile gets updated, but the actual executable within the .app file never gets updated. And this causes push notifications to never get to the device. So what i need to get working is the ability to build and sign an app from command line with the app having a bundle id that is populated dynamically using a variable. And I cannot seem to get this working.
THE RESULTS
The xcodebuild runs successfully and works perfectly. The app appears to be built and signed properly as .MOCK and using the _MOCK provisioning profile!
BUT! The generating of the IPA file has an issue, I have an issue with the codesign.
Notice, that I built the app without any code signing entitlements. codesign gives me this error:
warning: Application failed codesign verification. The signature was invalid, contains disallowed entitlements, or it was not signed with an iPhone Distribution Certificate. (-19011)
Executable=/Users/CI/Documents/workspace/build3/MyApp.app/MyApp
codesign_wrapper-4.1: using Apple CA for profile evaluation
Illegal entitlement key/value pair: application-identifier, UXXXXXX.au.com.blah.
AssertMacros: filter_entitlements(entitlements_whitelist, entitlements_requested, allowable_entitlements), file: codesign_wrapper.c, line: 932
- (null
Notice that it has not picked up the bundle_suffix. Also when i view the MyApp.xcent file that codesign references, I notice it has UXXXXXX.au.com.blah. in it. It has not picked up the value of the bundle_suffix!
So then, what i tried is to create an entitlements.plist file for my MOCK build configuration and add a link to the file under 'code signing entitlements' for MOCK configuration under the build settings. But now i get a different error, and its rather disturbing:
/usr/bin/codesign --force --sign 5XXXXXXXXXXXXXXXXXXX2c --resource-rules=/Users/CI/Documents/workspace/build3/MyApp.app/ResourceRules.plist --entitlements /Users/CI/Library/Developer/Xcode/DerivedData/MyApp-fasiktlyysoxjpgalujkfjpyiyeo/Build/Intermediates/MyApp.build/MOCK-iphoneos/MyApp.build/MyApp.xcent /Users/CI/Documents/workspace/build3/MyApp.app
Validate /Users/CI/Documents/workspace/build3/MyApp.app
cd /Users/Shared/Jenkins/Home/jobs/MyApp-MOCK-HourlyBuilds/workspace
setenv PATH "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/git/bin"
setenv PRODUCT_TYPE com.apple.product-type.application
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/Validation /Users/CI/Documents/workspace/build3/MyApp.app
warning: This bundle is invalid. The application-identifier entitlement is not formatted correctly; it should contain your 10-character App ID Seed, followed by a dot, followed by your bundle identifier: UXXXXXXXX.au.com.amp.blah.MOCK (-19054)
Unable to validate your application. - (null)
This time is has actually picked up the proper bundle identifier!! It says MOCK it it. But it is complaining that this bundle is invalid... but it looks perfectly valid to me!! Why is it not working?
This is my entitlements.plist file that I manually created and added to the project (and reference in 'code signing entitlements'):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>application-identifier</key>
<string>UXXXXXXXXXXX.au.com.amp.blah.MOCK</string>
<key>aps-environment</key>
<string>production</string>
<key>get-task-allow</key>
<false/>
<key>keychain-access-groups</key>
<array>
<string>UXXXXXXXXXXX.au.com.amp.blah.MOCK</string>
</array>
</dict>
</plist>
Any help would be greatly appeciated, many thanks!
P.S. I know that a way to get around this issue would be to create a different Target for each of my builds. But i dont really want this, as it is a pain maintaining multiple Targets. I really wanted to try and get away with this without having multiple Targets if I can.
P.S.S. I know another way to get around this issue is to sign the app initially with a .* provisioning profile and then resign the app after with the proper profile, however this does not work for me. As the executable file within .app still keeps references to the .* provisioning profile. And thus push notifications can never be picked up by this device. I get the “no valid 'aps-environment' entitlement string found for application” error.
I am running a similar setup for my iOS builds via Jenkins, with the goal of allowing side-by-side installation of the app (production, staging, qa, dev) and ran into the same problem as you.
In the end, I stumbled upon this answer and modified it to include the .xcent file which is part of the xcodebuild (check build output for the path) for the --entitlements flag. This means you do not have to manually create the entitlements file, but can use the exact one xcodebuild produces for you.
I too was using xcrun PackageApplication, but this does NOT support entitlements so re-signing using this tool would lose the entitlements.
So, after running xcodebuild I use plistbuddy to modify my info.plist file to update the settings bundle, etc. (this may not be required for you) and I unpack the ipa, copy the profile and info.plist into the unpacked payload, re-sign and re-pack:
pushd ${SCRIPT_DIR}
unzip "${PROJECT_NAME}.${CURRENT_ENV_NAME}.ipa"
rm -r "Payload/${PROJECT_NAME}.app/_CodeSignature" "Payload/${PROJECT_NAME}.app/CodeResources" 2> /dev/null | true
cp "${PROFILE}" "Payload/${PROJECT_NAME}.app/embedded.mobileprovision"
cp "${BUILD_DIR}/${BUILD_TARGET}-iphoneos/${PROJECT_NAME}.app/Info.plist" "Payload/Yappem.app/Info.plist"
/usr/bin/codesign -f -s "${CODE_SIGN_IDENTITY}" --resource-rules "Payload/${PROJECT_NAME}.app/ResourceRules.plist" --entitlements "${XCENT_FILE}" "Payload/${PROJECT_NAME}.app"
if [ $? != 0 ]; then
echo Error Signing Project
exit 1
fi
rm "${PROJECT_NAME}.${CURRENT_ENV_NAME}.ipa"
zip -qr "${PROJECT_NAME}.${CURRENT_ENV_NAME}.ipa" Payload
popd

MonoTouch: Create iOS AppStore-Version from command line

I want to build my ios-apps Appstore-ready directly from the command line with the mdtool from MonoTouch (Xamarin) so that Jenkins can kick in and produce the uploadable package right away.
I use the following command:
'/Applications/Xamarin Studio.app/Contents/MacOS/mdtool' -v build '--configuration:AppStore|iPhone' MyAppProject.csproj
Now, the build runs, uses my AppStore Provisioning Profile and creates the files in my bin/iPhone/AppStore - folder.
Now, according to the documentation of Xamarin, I should zip the created app-file in the bin/iPhone/AppStore and select it in xCode Application Loader like shown in the screenshot:
But the Application Loader shows every file grayed out, so there is no chance to continue.
What if you rename the .zip extension to .ipa?
I think you should not choose "Open package" but "Deliver Your App".
You can also use the xcrun ("XCode Run") command line tool to with the "PackageApplication" argument to package an ".app" into an ".ipa" and optionally specify a signing identity and provisioning profile at the same time.
Something like:
/usr/bin/xcrun -sdk iphoneos PackageApplication -v "Ios.app" -o "Ios.ipa" --sign "[DEVELOPER_NAME]" --embed "[PROVISONING_PROFILE]”
More info on xcrun here:
https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/xcrun.1.html

iOS Enterprise: Re-certify existing IPA with new certificate

We are enrolled in the iOS Enterprise Program. The provisioning profile used for our released apps is about to expire, so I got a new certificate and provisioning profile.
I need to re-distribute some of our apps with the new provisioning profile, without building them anew. How?
(I vaguely remember seeing a utility program that did exactly this: You choose an IPA and a provisioning profile, and it would create a new IPA using the new profile and certificate. What was the tool’s name, and where can I get it?)
In theory whoever built the last IPA in XCode should have used Archive - this creates a build you can sign to create an IPA (using XCode).
You could also try using the command line signing tool XCRun to re-sign the App bundled in your existing IPA:
http://skabber.com/package-your-ios-application-with-xcrun
OK, turns out when you know what term to google, there‘s lots of excellent resources…
They all point to xcrun. I made it work with this shell snippet, adapted from this promising build script:
APP_FILENAME=MyApp.app
BUILD_DIRECTORY=/Path/To/Target/Dir
IPA_FILENAME=MyApp.ipa
DISTRIBUTION_CERTIFICATE='iPhone Distribution'
PROVISIONING_PROFILE_PATH='/Path/To/Profile.mobileprovision'
/usr/bin/xcrun -sdk iphoneos PackageApplication -v "$APP_FILENAME" -o "$BUILD_DIRECTORY/$IPA_FILENAME" --sign "$DISTRIBUTION_CERTIFICATE" --embed "$PROVISIONING_PROFILE_PATH"
The codesign command-line utility, included with the iOS SDK tools, will allow adding/changing the certificate and provision with which a developer built app is signed.
As hotpaw2's anwaswer states. You can also resign using the codesign tool.
The way I do it (this may not be the most efficient, but it works)
Rename the .ipa to a .zip and extract
Run The following:
/usr/bin/codesign -f -s "iPhone Distribution: Company Name" "Payload/MyApp.app"
Re-zip the Payload folder and rename to .ipa
Note: You can also use this method to edit the embedded.mobileprovisioning file! Just remember to remove the .DS_Store (rm Payload/.DS_Store) if you are using finder.
You can do manual way if you just resigning app from same account with following steps.
All this is using shell script and super easy provided you know how to use shell commands.
Rename IPA to zip
unzip this file to temp folder
Remove the old _CodeSignature folder from all targets (if you have multiple targets like main,watch, watch extn, siri, widget, message, etc)
bring all the targets prov-profiles in one folder and replace all the embedded.provisioningprofile files for each target with the new ones
remove the archived....xccent file as this is old one (optional)
code sign with the entitlements.plist created for all the entitlements if any used by the app.
Zip the folder back after code sign all okay with no errors
Rename the zip to IPA
Note: To validate the IPA before upload to apple you can just use the altool from inbuild XCode App Loader to check the new IPA.
Reference: The steps for commands is also explained here:
http://www.enterpriseios.com/forum/topic/Resigning_3rd_party_apps
If you want to get rid of manual sign use the fastlane tool as its quite simple and easy to configure.https://fastlane.tools/

How to re-sign the ipa file?

How do I sign the .ipa file with a provisioning profile after I generate an IPA like the following with a different provision profile? I would like to sign the IPA with an ad-hoc provisioning profile for beta testing, and then re-sign the exact IPA with an app submission provisioning profile for the app store.
/usr/bin/xcrun -sdk iphoneos PackageApplication -v "${RELEASE_BUILDDIR}/${APPLICATION_NAME}.app" -o "${BUILD_HISTORY_DIR}/${APPLICATION_NAME}.ipa" --sign "${DEVELOPER_NAME}" --embed "${PROVISONING_PROFILE}"
It's really easy to do from the command line. I had a gist of a script for doing this. It has now been incorporated into the ipa_sign script in https://github.com/RichardBronosky/ota-tools which I use daily. If you have any questions about using these tools, don't hesitate to ask.
The heart of it is this:
CODESIGN_ALLOCATE=`xcrun --find codesign_allocate`; export CODESIGN_ALLOCATE
IPA="/path/to/file.ipa"
PROVISION="/path/to/file.mobileprovision"
CERTIFICATE="Name of certificate: To sign with" # must be in keychain
# unzip the ipa
unzip -q "$IPA"
# remove the signature
rm -rf Payload/*.app/_CodeSignature
# replace the provision
cp "$PROVISION" Payload/*.app/embedded.mobileprovision
# sign with the new certificate (--resource-rules has been deprecated OS X Yosemite (10.10), it can safely be removed)
/usr/bin/codesign -f -s "$CERTIFICATE" Payload/*.app
# zip it back up
zip -qr resigned.ipa Payload
Your new signed app is called resigned.ipa
Check iResign for an easy tool on how to do this!
[edit] after some fudling around, I found a solution to keychain-aware resigning. You can check it out at https://gist.github.com/Weptun/5406993
Kind of old question, but with the latest XCode, codesign is easy:
$ codesign -s my_certificate example.ipa
$ codesign -vv example.ipa
example.ipa: valid on disk
example.ipa: satisfies its Designated Requirement
The answers posted here all didn't quite work for me. They mainly skipped signing embedded frameworks (or including the entitlements).
Here's what's worked for me (it assumes that one ipa file exists is in the current directory):
PROVISION="/path/to/file.mobileprovision"
CERTIFICATE="Name of certificate: To sign with" # must be in the keychain
unzip -q *.ipa
rm -rf Payload/*.app/_CodeSignature/
# Replace embedded provisioning profile
cp "$PROVISION" Payload/*.app/embedded.mobileprovision
# Extract entitlements from app
codesign -d --entitlements :entitlements.plist Payload/*.app/
# Re-sign embedded frameworks
codesign -f -s "$CERTIFICATE" --entitlements entitlements.plist Payload/*.app/Frameworks/*
# Re-sign the app (with entitlements)
codesign -f -s "$CERTIFICATE" --entitlements entitlements.plist Payload/*.app/
zip -qr resigned.ipa Payload
# Cleanup
rm entitlements.plist
rm -r Payload/
Fastlane's sigh provides a fairly robust solution for resigning IPAs.
From their README:
Resign
If you generated your ipa file but want to apply a different code signing onto the ipa file, you can use sigh resign:
fastlane sigh resign
sigh will find the ipa file and the provisioning profile for you if they are located in the current folder.
You can pass more information using the command line:
fastlane sigh resign ./path/app.ipa --signing_identity "iPhone Distribution: Felix Krause" -p "my.mobileprovision"
It will even handle provisioning profiles for nested applications (eg. if you have watchkit apps)
I've updated Bryan's code for my Sierra iMac:
# this version was tested OK vith macOs Sierra 10.12.5 (16F73) on oct 0th, 2017
# original ipa file must be store in current working directory
IPA="ipa-filename.ipa"
PROVISION="path-to.mobileprovision"
CERTIFICATE="hexadecimal-certificate-identifier" # must be in keychain
# identifier maybe retrieved by running: security find-identity -v -p codesigning
# unzip the ipa
unzip -q "$IPA"
# remove the signature
rm -rf Payload/*.app/_CodeSignature
# replace the provision
cp "$PROVISION" Payload/*.app/embedded.mobileprovision
# generate entitlements for current app
cd Payload/
codesign -d --entitlements - *.app > entitlements.plist
cd ..
mv Payload/entitlements.plist entitlements.plist
# sign with the new certificate and entitlements
/usr/bin/codesign -f -s "$CERTIFICATE" '--entitlements' 'entitlements.plist' Payload/*.app
# zip it back up
zip -qr resigned.ipa Payload
Unzip the .ipa file by changing its extension with .zip
Go to Payload. You will find .app file
Right click the .app file and click Show package contents
Delete the _CodeSigned folder
Replace the embedded.mobileprovision file with the new provision profile
Go to KeyChain Access and make sure the certificate associated with the provisional profile is present
Execute the below mentioned command:
/usr/bin/codesign -f -s "iPhone Distribution: Certificate Name" --resource-rules "Payload/Application.app/ResourceRules.plist" "Payload/Application.app"
Now zip the Payload folder again and change the .zip extension with .ipa
Hope this helpful.
For reference follow below mentioned link:
http://www.modelmetrics.com/tomgersic/codesign-re-signing-an-ipa-between-apple-accounts/
Try this app
http://www.ketzler.de/2011/01/resign-an-iphone-app-insert-new-bundle-id-and-send-to-xcode-organizer-for-upload/
It supposed to help you resign the IPA file. I tried it myself but couldn't get pass an error with Entitlements.plist. Could just be a problem with my project. You should give it a try.
I have been using https://github.com/xndrs/XReSign and it is working really well.

Resources