How to build and sign an iOS app on separate machines? - ios

We have an iOS app which is built using a series of Bash scripts run by Jenkins. As things are today, we build an xcarchive using this command:
xcodebuild archive -workspace "..." -scheme "..." -configuration "Release" -archivePath "..."
This builds the app and signs it using the certs specified in the provisioning profile which is set using an xcconfig. Once it is complete, we then turn it into an IPA using:
xcodebuild -archivePath "..." -exportArchive -exportOptionsPlist "${export_options_plist}" -exportPath "..."
This IPA can then be uploaded to Hockey or to the App store depending on the xcconfig we use (we swap them out to create different builds).
We now want to make sure our certificates are kept safe as much as possible. This means we want to perform the build on one machine, but the signing on another. In order to do that, we need to do this:
Create an unsigned xcarchive
Transfer the xcarchive to the signing machine
Turn the xcarchive into a signed IPA
Step 2 can be ignored for now though, so lets just focus on steps #1 and #3.
Creating the unsigned xcarchive can be done by adding the arguments CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO to the archive command.
Signing the IPA is much trickier though. We assumed we could just create the IPA again and use the codesign command to sign the binary in the IPA. This had a couple of problems though. The first is that the .entitlements file we had for the app wasn't respected. We had to pass this as a flag to the signing command. Then we realised that we had to correct all the variables in the .entitlements file since Xcode was no longer replacing them with the correct values. Then we realised that we had to do this for each extension we had.
We finally got this all working, with the correct entitlements, replacing the variables and everything was signed, but when I tried uploading the new signed IPA to Hockey it rejected it. The error message wasn't helpful either.
We diff'ed a build with the previous system with the new system and each binary was different. We're not sure if this is a codesigning issue, or just a timestamp change, but there are changes. Furthermore, we discovered that my extensions are all missing archived-expanded-entitlements.xcent files, plus possibly more issues.
It definitely seems like we are going about this the wrong way. We clearly shouldn't have to re-do everything just to sign on a different machine, so where are we going wrong? How are we supposed to build on one machine and sign on another?
P.S. Our current tools use xcodebuild directly, but we have support for fastlane for other parts of our build process, so we are happy to use it if needed.
Update: We have a "solution" to this which is to sign the Release builds with a dev cert, then resign them using the distribution one. This solves all the problems with entitlements being populated etc. but still requires each binary to be resigned and entitlements combined, etc. so I'm curious if there is a better solution.

Please follow the steps to create an unsigned xcarchive
Set ‘Code Signing Identity’ = ‘Don’t Code Sign’
• Select Targets (‘’) -> Build Settings and find the ‘Signing’ section.
• Set ‘Code Signing Identity’ = ‘Don’t Code Sign’
Set Bundle Identifier = ‘’
Set Version = 1.0 //That you need to send
Set Build = 5 //That you need to send
Remove ‘Automatically manage singing’ flag.
Open the terminal and go to the project root folder. Then run the following command.
xcodebuild -workspace <ProjectName>.xcworkspace -scheme <ProjectName> -configuration Release clean archive -archivePath buildArchive/<ProjectName>.xcarchive CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO
After successfully completing, it will create a new ‘buildArchive’ folder and inside that a ‘.xcarchive’ file.
You can Zip that ‘.xcarchive’ file and transfer the xcarchive to the signing machine.

We worked on this for several weeks along with other teams in the company. All of us came to the same conclusion, there is no better option than signing with a dev cert and then re-signing each and every binary with the prod cert afterwards. It's not a straight forward process, but that's what we have been left with.

This might work for you I think
Create an unsigned IPA on your build machine.
Have a script in the build machine that transfers the IPA to your
signing machine.
Use the FloatSign script on the signing machine to resign the
IPA.

Related

xcodebuild using wrong provisioning profile

I have a bash script where I am trying to automate pushing an IPA to TestFlight. Currently this script is successfully uploading to the app-store with an ad-hoc provisioning profile and not my distribution profile as such I am unable to push the build to TestFlight as it does not have the beta-reports-active key. This is easily fixable from within XCode but I have had no luck using command line which is integral to what I want to do. This is my current command trying to use manual signing:
xcodebuild archive -workspace $NAME.xcworkspace -allowProvisioningUpdates -scheme $NAME -configuration Release -archivePath ../builds/$NAME.xcarchive DEVELOPMENT_TEAM=$TEAM_ID CODE_SIGN_STYLE=Manual CODE_SIGN_IDENTITY="iOS Distribution: MY_NAME" PROVISIONING_STYLE=Manual PROVISIONING_PROFILE_SPECIFIER="PROVISIONING PROFILE "
Is there a way of getting the correct provisioning profile through command line
EDIT
Examples of what I have tried:
Downloading and inserting the provisoning profile int0 ~/Library/MobileDevice/Provisioning\ profiles and then using PROVSIONING_PROFILE_SPECIFIER to point to the profile
Inserting the app-store method into the export options plist file
Creating new ExportOptions file that specifies manual signing as well as the provision profile being used - so far getting a signing error due to no provisioning profile being found
Hope this ^ is clear
I had a similar problem, I was using fastlane to push to testflight and it automatically kept pulling the wrong provisioning profile..
When I dug deeper by running
xcodebuild -showBuildSettings -workspace Freshdesk.xcworkspace -scheme <My Build scheme>
I realised that no matter what scheme I picked I kept getting the same provisioning profile in the command line.
I then dug into xcode and chanced on this parameter
This was set to staging and I could never sign my app for the app store build, I changed it to production and it fixed my problems
You can find this under "configurations" in the info tab of your project and not the target
I hope this helps!

ERROR ITMS-90046 using xctool / xcodebuild vs XCode Archive's success

I've got a command line script I use to compile, archive and submit my ios builds to ITC for TestFlight deployment. They work great, but I recently ran into an issue when trying to use an embedded framework within my otherwise working project. My script compiles and archives the project successfully but is getting ITC signing errors because of the embedded binary conflict.
xctool -workspace $BASE_DIR/$PROJECT_NAME -scheme $SCHEME -configuration $CONFIG clean archive -archivePath ./$PRODUCT_NAME.xcarchive
xcodebuild -exportArchive -archivePath ./$PRODUCT_NAME.xcarchive -exportPath $PRODUCT_NAME -exportFormat ipa -exportProvisioningProfile "$DIST_PROVISIONING_PROFILE_NAME"
# result is successful, with .ipa file generated
After a successful compilation my script tries to upload to ITC, and fails with the below msg. I get the same message if I try to upload the generated IPA file to ITC myself using Application Loader tool.
ERROR ITMS-90046: "Invalid Code Signing Entitlements. Your application
bundle's signature contains code signing entitlements that are not
supported on iOS. Specifically, value 'XXXXXXXXX.com.domain.Product'
for key 'application-identifier' in
'Payload/Product.app/Frameworks/Charts.framework/Charts' is not
supported. This value should be a string starting with your TEAMID,
followed by a dot '.', followed by the bundle identifier.
There is no application-identifier string used in my project or settings that I can find with a global search.
Extra Info
com.domain.Product would be my project's main bundleIdentifier, which has a distribution certificate and provisioning profile generated for it. Without the embedded binary that works just fine. The "Charts" embedded project has a bundleIdentifier but the team is set to "None" in the Info tab, and signing is set to Automatic. Since it is an embedded binary/framework, I'm assuming it doesn't independently sign it. When using Xcode's Archive, it is listed as a subset of the main Project with no independent identifier or entitlements.
I have also tried creating an independent appId and distribution provisioning profile for the embedded binary called "com.domain.ProductCharts" and setup the project correctly. This does not change the error.
I have further tried setting the embedded binary's project to use the same bundleIdentier and settings as the parent Project, but this does not change the error.
Why is xctool/xcodebuild unable to properly compile and sign this to get through to ITC, while the native Archiver can?
Currently, I encountered what I think is a bug in xcodebuild command similar to this, way I fixed it for me was to setup provisioning profile in the project settings. Try updating your project and run build again.
The investigation into the issue was here: https://forums.developer.apple.com/thread/14378
But others reported problem with associated domains:
SO question: Apple Store submit fails with Error ITMS-90046, but Associated Domains is not among entitlements
What is your OS, XCode ... etc?
Just a guess: Maybe you need to specify an application-identifier in your Entitlements.plist if you use the command line. Here https://developer.apple.com/library/ios/qa/qa1710/_index.html it is stated that in "In modern versions of Xcode.."
You said:
They work great, but I recently ran into an issue...
Have you created a new profile meanwhile and now there are two? Or two certificates? Here is a description on how to check your entitlements. Maybe this helps.
Creating .entitlements for the embedded framework will solve the issue only in Xcode 7.x. In the version 8.x the issue still exists.

Automating iOS/WatchKit App Store submission - Code signing issue

I have a rather typical iOS 8 iOS/ObjC/Xcode 6.4 application, which includes a WatchKit extension. I have no trouble manually submitting to the App Store using Xcode using the Archive menu option.
We use a build server (Bamboo but it shouldn't matter). The build server currently automates builds and distributions through HockeyApp, but we manually build and upload to iTunes Connect using Xcode. We would like to automate the builds for the iTunes Connect, so we're certain same codebase is used for both HockeyApp and iTunes Connect (both TestFlight and App Store).
I'm having a heck of a time getting the script working for iTunes Connect, due (I believe) to the three targets that need signing (iOS app, WatchKit Extension, and Watch App).
I found this answer to a related question, which has been very helpful: https://stackoverflow.com/a/29605731. That suggests putting variables into the Provisioning Profile settings for the three targets. This works for building. But that question doesn't involve uploading to iTunes Connect, which is where I'm seeing trouble.
So my script looks like this:
APP_PROFILE="[the hex string]"
WATCHKITEXT_PROFILE="[another hex string]"
WATCHAPP_PROFILE="[one more hex string]"
First I make the xcarchive:
xcodebuild archive -project myProject.xcodeproj -scheme "myScheme" -archivePath myProject.xcarchive APP_PROFILE="${APP_PROFILE}" WATCHKITEXT_PROFILE="${WATCHKITEXT_PROFILE}" WATCHAPP_PROFILE="${WATCHAPP_PROFILE}"
which works fine. Then I export the archive to an .ipa:
xcodebuild -exportArchive -archivePath "myProject.xcarchive" -exportPath "myPath" -exportFormat ipa APP_PROFILE="${APP_PROFILE}" WATCHKITEXT_PROFILE="${WATCHKITEXT_PROFILE}" WATCHAPP_PROFILE="${WATCHAPP_PROFILE}"
which also reports success. Then I need to send the .ipa to iTunes Connect using the Application Loader's command-line tool (here I'm just verifying):
altool --validate-app -f "myProject.ipa" -u myUsername -p myPassword
which spits back this set of error messages:
*** Error: Unable to validate archive 'myProject.ipa': (
"Error Domain=ITunesConnectionOperationErrorDomain Code=1091 \"Invalid Signature. A sealed resource is missing or invalid. Make sure you have signed your application with a distribution certificate, not an ad hoc certificate or a development certificate. Verify that the code signing settings in Xcode are correct at the target level (which override any values at the project level). Additionally, make sure the bundle you are uploading was built using a Release target in Xcode, not a Simulator target. If you are certain your code signing settings are correct, choose \"Clean All\" in Xcode, delete the \"build\" directory in the Finder, and rebuild your release target. For more information, please consult https://developer.apple.com/library/ios/documentation/Security/Conceptual/CodeSigningGuide/Introduction/Introduction.html\" UserInfo=0x7fec4be78b80 {NSLocalizedRecoverySuggestion=Invalid Signature. A sealed resource is missing or invalid. Make sure you have signed your application with a distribution certificate, not an ad hoc certificate or a development certificate. Verify that the code signing settings in Xcode are correct at the target level (which override any values at the project level). Additionally, make sure the bundle you are uploading was built using a Release target in Xcode, not a Simulator target. If you are certain your code signing settings are correct, choose \"Clean All\" in Xcode, delete the \"build\" directory in the Finder, and rebuild your release target. For more information, please consult https://developer.apple.com/library/ios/documentation/Security/Conceptual/CodeSigningGuide/Introduction/Introduction.html, NSLocalizedDescription=Invalid Signature. A sealed resource is missing or invalid. Make sure you have signed your application with a distribution certificate, not an ad hoc certificate or a development certificate. Verify that the code signing settings in Xcode are correct at the target level (which override any values at the project level). Additionally, make sure the bundle you are uploading was built using a Release target in Xcode, not a Simulator target. If you are certain your code signing settings are correct, choose \"Clean All\" in Xcode, delete the \"build\" directory in the Finder, and rebuild your release target. For more information, please consult https://developer.apple.com/library/ios/documentation/Security/Conceptual/CodeSigningGuide/Introduction/Introduction.html, NSLocalizedFailureReason=iTunes Store operation failed.}"
I get the same error if I use the Application Uploader GUI.
I'm confident I'm using the correct profiles in the script, as when I export an archive in Xcode these are the three Xcode selects (that export will validate/submit fine).
I'm at a loss where to look next. Any and all help is appreciated - thanks!

Xcode build failing randomly

We have an iOS automated build system that is randomly failing the codesign for certain projects.
The build system uses xcodebuild (followed by xcrun) to build and package the application. We use this process across multiple apps. The build machines we run this on have multiple distribution signing certificates, and are running Xcode 5.1.1 (5B1008) and 10.9.4. We've been using the system for about two years now, and builds work fine. When they don't work, there's usually a clear xcodebuild error message. But right now we are getting random failures of the codesign call on xcodebuild for two of our apps.
The xcodebuild command is as follows:
xcodebuild -verbose -project ./src_dir/TechApp.xcodeproj ONLY_ACTIVE_ARCH=NO ARCHS="armv7 armv7s arm64" -scheme ${SCHEME} QA PROVISIONING_PROFILE=${PROFILE} CODE_SIGN_IDENTITY=${IDENTITY} CONFIGURATION_BUILD_DIR=./bld_dir/builds/QA build
And, after lots and lots of xcodebuild compile statements, it fails with the following:
CodeSign /Users/bldUser/buildScripts/archive_dir/1404933111/bld/bld_dir/builds/QA/Tech\ App.app
cd /Users/bldUser/buildScripts/archive_dir/1404933111/bld/src_dir
export CODESIGN_ALLOCATE=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate
export 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"
Using code signing identity "iPhone Distribution: Build Certificate" and provisioning profile "BuildWildcard" (C137C14D-630F-4D67-BD2B-2FD4AB4F2BA4)
/usr/bin/codesign --force --sign 637514541007B62BCEA94ACC41A98A0E1391C3D4 --resource-rules=/Users/bldUser/buildScripts/archive_dir/1404933111/bld/bld_dir/builds/QA/Tech\ App.app/ResourceRules.plist --entitlements /Users/bldUser/buildScripts/archive_dir/1404933111/bld/build/TechApp.build/Debug-iphoneos/TechApp\ QA.build/Tech\ App.xcent /Users/bldUser/buildScripts/archive_dir/1404933111/bld/bld_dir/builds/QA/Tech\ App.app
** BUILD FAILED **
The projects in which this are failing are big apps... and they have multiple dependent projects attached to them (and I think that it might be the dependent projects that are contributing to the random failure of the codesign, but I'm not sure).
The thing is that this randomly fails at this statement. If I run it again, it will work fine. So it's the randomness that confuses me. And there really is not any error message. It just says "BUILD FAILED". Some things I've tried to get this to work:
I've passed in additional parameters into xcodebuild OTHER_CODE_SIGN_FLAGS=--verbose=4 --continue --deep in order to see if any combination of these parameters "help." This was based on the problem described in this link, as it seemed to match the failure conditions for our particular projects that are failing. This post had me the most interested, as it seems like this issue may be related to the OS + build environment + the fact that the projects this is failing on have lots of sub-projects attached.
We currently have all our certificates in the login.keychain... but, as per this link (amongst others) there's a suggestion to run certificates off of a build-specific keychain. This is great, and a much cleaner way to do things-- but, after trying this, this had no impact for the issue above.
I thought maybe this might have to do with confusion on certificates-- so I've removed all iPhone Distribution certificates except the the one I need for these apps, and it still comes back with this error.
I've gone in to each of the targets for the projects, including the sub-projects, and put in code signing identity just to make sure there wasn't a possibility that there was some project or sub-project setting that would pick the wrong certificate. In addition, on the xcodebuild command above, I've put in the explicit scheme name and provisioning profile id-- so this is not an issue where it can't find the provisioning profile/certificate combination (or at least I don't think it is-- there's no indicator that it can't find the provisioning profile or certificate)
Given that it's random, I suspect it's either (1) a case where there is some unset code signing value, and it therefore randomly picks one; or (2) some issue with xcode or the os that was only recently introduced.
Any thoughts or ideas on what to try would be much appreciated.
One update:
This works just fine when run through Xcode. So this is something specific to xcodebuild for these projects. When compiled through Xcode: it works 100% of the time. When compiled through xcodebuild: it works like 25-50% of the time. So I'm really hoping there's something I"m missing on the xcodebuild command and this does not require an actual project change (since it works when compiled directly through Xcode).
Update on trojanfoe's question:
There may very well be an issue with spaces. This is the actual xcodebuild call on one of the projects:
xcodebuild -verbose -project /Users/bldUser/buildScripts/archive_dir/1404904225/bld/src_dir/MyTechApp.xcodeproj ONLY_ACTIVE_ARCH="NO" ARCHS="armv7 armv7s arm64" -scheme "TechApp Dev" PROVISIONING_PROFILE="" CODE_SIGN_IDENTITY="iPhone Distribution: Build Certificate" CONFIGURATION_BUILD_DIR="/Users/bldUser/buildScripts/archive_dir/1404897462/bld/bld_dir/builds/Dev" build
After running the command above, there is (lots) of build commands (there are lots and lots of warnings, but no errors). It finally stops at the following:
CodeSign /Users/bldUser/buildScripts/archive_dir/1404897462/bld/bld_dir/builds/Dev/Tech\ App.app
cd /Users/bldUser/buildScripts/archive_dir/1404904225/bld/src_dir
export CODESIGN_ALLOCATE=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate
export 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"
Using code signing identity "iPhone Distribution: Build Certificate" and provisioning profile "BuildWildcard" (C137C14D-630F-4D67-BD2B-2FD4AB4F2BA4)
/usr/bin/codesign --force --sign 637514541007B62BCEA94ACC41A98A0E1391C3D4 --resource-rules=/Users/bldUser/buildScripts/archive_dir/1404897462/bld/bld_dir/builds/Dev/Tech\ App.app/ResourceRules.plist --entitlements /Users/bldUser/buildScripts/archive_dir/1404904225/bld/build/MyTechApp.build/Debug-iphoneos/TechApp\ Dev.build/Tech\ App.xcent /Users/bldUser/buildScripts/archive_dir/1404897462/bld/bld_dir/builds/Dev/Tech\ App.app
** BUILD FAILED **
All of the "cd" commands and the "export" commands are run as part of the codesign command. In terms of the xcodebuild statement, we're leaving the provisioning profile blank so it picks up a default-- although even if I specify the specific provisioning profile, it will still fail (and from the code sign above, it IS picking up the correct provisioning profile). The above also specifies the scheme. This is normally run from a bash script where it will loop through an array of schemes and generate builds via xcodebuild for each scheme. As you can see above, there are spaces in the scheme and the project and the product name, so I would not be at all surprised if that were an issue in some way. I'm not sure why it would work one time and not another, but I'm going to try out removing spaces. The src_dir and the funky archive_dir numeric is a directory created by our build system, so the files are all checked out to the src_dir location.

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/

Resources