Codesigning iOS applications (APNS Enabled) without using XCode - ios

I want to build a single window Mac application, which can be used to codesign iOS applications without using XCode.
Many of our clients use "Enterprise License" to distribute their apps. Each year they need to be resigned and its a repetitive work. Their requirements are following
Apps make use of APNS
They don't want to share their Enterprise License
Bundle identifier should be replaceable while signing with their certificate
They have certificates with same name in Keychain
Userinterface has the following fields
Path to the *.ipa file
Path to the *.mobileprovision file
Keychain name (optional incase more than one certificate with same name exists)
Name of the certificate (iPhone Developer : .....)
I was able to codesign application, but APNS is not working after resigning. Or is it not possible to resign applications making use of bundleIdentifier?
And also I would like to add a feature of drop down list of certificates available in Keychain for improved useability. Any pointers would be great help

To enable push notifications, the app ID and provisioning profile will need to have that configured and allowed by Apple (through the portal). You can't enable it for arbitrary provisioning profiles/apps just by resigning.
During codesigning, the entitlements need to have the apns-environment key set to sandbox/production depending on what the app uses. This will then be verified at runtime by iOS. If you are using a third-party signing tool, it should take the apns-environment value from the provisioning profile.
For debugging, you can look at the entitlements for a .app with this command:
codesign -d --requirements - --entitlements - path/to/My.app
You should see an apns-environment value, but only if the provisioning profile had that enabled.

Just spent several hours researching this same issue and discovered the following process. Taking Mike's comments one step further, providing the following command line for others running into the same issue.
I am starting with an xcode release build using a bundle id that has been configured for production push notification.
From the terminal window run the following commands - replacing the "CAPITAL SECTIONS" with your info
codesign -d --entitlements -"NAME OF APP.app" > entitlements.plist
codesign -f -s "SIGNING CERTIFICATE NAME" --resource-rules "NAME OF APP.app/ResourceRules.plist" --entitlements entitlements.plist "NAME OF APP.app"
Hope this helps the next person struggling with this same issue

Related

Is entitlement.plist file required while re-signing a development IPA with distribution certificate and profile of same account?

In my organization, the distribution certificate and app store provisioning profile are located and installed on a Mac machine present inside a Lab environment to which only a lab manager has access to.
For me to upload an app's IPA to app store, I need to archive a development IPA (using dev cert and profile in Release configuration mode) on my local Mac and then send across this IPA to the lab manager.
The lab manager uses a python re-signing script to re-sign the IPA on the lab Mac.
Do I also need to explicitly send a entitlements.plist file along with the IPA. My app does not use any capabilities as of now, not even Push Notifications. All Capabilities in Xcode are Off and on developer portal also the app identifier has Game Center and In-House Purchase as checked by default under the Capabilities.
I am assuming since it is the same Apple account using which lab manager will be re-signing the IPA and the app store profile present on the lab Mac contains its own entitlements, I do not need to send an explicit entitlements.plist file. Also, I assume the app will not get rejected in review.
Are these assumptions correct? Thanks in advance.
You can not magically attach an entitlements file during export; it has to be there during archiving. But you do not find out whether you got it "right" (in Apple's eyes) until distribution time.
So a situation where archiving happens in one place and exporting happens in another is not going to be a happy one.
I would describe this entire situation as unacceptable. I have had many occasions, just working on my own machine, where I was able to archive but then unable to upload to the app store or TestFlight because of an entitlements issue. And often there was no "real" issue: I just needed to do a bunch of goat sacrifices and fooling around with the settings (e.g. turn entitlements on and off). The point is, you don't know there's an issue until you export — and then to find out whether you fixed it you have to build / archive again.
1) Entitlement plist can be given while resining an ipa like below but this is optional.
codesign --entitlements entitlements.xml -f -s "IDENTITY" Payload/<app_name>.app
Please refer How do I resign app with entitlements?
2) To resign an ipa, you can follow below procedure (without giving Entitlement).
Requisites:
Distribution profile
Distribution certificate
Assuming Distribution profile stored in Desktop ~/Desktop/AdHoc.mobileprovision
Procedure :
1) unzip ipa using following command,
unzip app.ipa
2) When you unzip it You will have as an output a directory called “Payload”.
3) remove _CodeSignature file from unzipped folder “Payload” as below
rm -rf Payload/MyApp.app/_CodeSignature/
4) Rename distribution profile which is stored in Desktop to embedded.mobileprovision
5) Copy distribution profile(embedded.mobileprovision from Desktop) to Payload/.app
cp ~/Desktop/AdHoc.mobileprovision Payload/MyApp.app/embedded.mobileprovision
6) Resign using below commands,
codesign -f -s “IDENTITY” --resource-rules Payload/MyApp.app/ResourceRules.plist Payload/MyApp.app
7) Zip payload to form an ipa as below
zip -qr <app_name>.ipa Payload/

Xcode's Bot always returns error

I got an issue with Xcode's Bot. It always returns the "User canceled the operation. Command /usr/bin/codesign failed with exit code 1" error string after running the command below:
/usr/bin/codesign --force --sign <MY_PRIVATE_KEY> --entitlements /Library/Developer/XcodeServer/Integrations/Caches/2cdd321641e8c114e4eba9819b017479/DerivedData/Build/Intermediates/MyApp.build/Debug-iphoneos/MyApp.build/MyApp.app.xcent /Library/Developer/XcodeServer/Integrations/Caches/2cdd321641e8c114e4eba9819b017479/DerivedData/Build/Products/Debug-iphoneos/MyApp.app
I can run this command in Terminal with sudo. I'm using Xcode 6.3.1 and OS X Server 4.1.53 in my Mac 10.10.4.
Thank for your help.
This looks like a code signing error. There are a few different reasons for this to happen so you will need to do some troubleshooting. Can other bots build on your server? If so then its probably a build settings issue in this specific project.
In the Xcode Project go to the Project Target that your trying to build, and then Build Settings, and Code Signing. Under the Provisioning Profile you can either choose Automatic or explicitly choose the correct provision, and then under the Code Signing Identity choose iOS Developer. This is probably where your issue is if its related to the project. Do you have a proper provision setup for the project on the Apple Developer Portal?
If you can't get any bots to run on your server then the issue could be with how you set up Xcode Server. Have you added the server to your team? Here is the blog post that I used to get mine up and running, although you don't need to do all of those steps in the post. Focus specifically on the Setup Certificates section and Setup Provisioning Profiles section.
I fixed the issue by copying the missing provisioning file from my local directory "/Users/phuongle/Library/MobileDevice/Provisioning Profiles" to "/Library/Developer/XcodeServer/ProvisioningProfiles". Do not use the downloaded provisioning file from developer.apple.com directly.
I just want to note here for everyone having the same issue with me.

Publishing IOS app on client's Enterprise App Store without source coce

I am developing an IOS app for a client. My client would like to publish the app on their private Enterprise App Store which is provided by MobileIron. However, I will not disclose the source code to my client. Is anyone familiar to MobileIron? Can my client publish the app on their Enterprise App Store if only an api file is provided? How to achieve it? Thank you!
Path of least resistance:
ask them for an invitation as a member of their Enterprise portal
archive and sign the app with a development cert & provisioning profile out of that portal
send them the .xcarchive file out of Organizer
they can then pop open the .xcarchive file in XCode, won't see the code, and can re-sign with their Enterprise cert and profile
The other answer will work but it's a pain in the neck compared to the above.
To resign an existing IPA do following steps in the terminal:
rm -rf Payload/<yourapp>.app/_CodeSignature/
cp <a valid and made for your bundle>.mobileprovision Payload/<yourapp>.app/embedded.mobileprovision
codesign -f -s "iPhone Distribution: <company>" --resource-rules Payload/<yourapp>.app/ResourceRules.plist Payload/<yourapp>.app
zip -r render3d.ipa Payload
Then remove the app from the device with Xcode
and drag the new ipa into xcode onto the device
EDIT:
see also:
Re-sign IPA (iPhone) and
How to re-sign the ipa file?

Xcode Command /usr/bin/codesign failed with exit code 1 : errSecInternalComponent

I am trying to add new provisioning profile to my Xcode, to test an app on the device. Here are the steps I followed:
Deleted all certificates and provisioning profiles
Create/Add IOS Dev Certificate
Add My IOS Device Online
Create IOS Provisioning Profile
Add IOS Provisioning Profile
Clean App
Build Then Run App
Set Codesigning nd Provisioning Profile In Build Settings
Lots of Googling > to no successes
Here is the error I get:
CSSM_SignData returned: 800108E6
/Users/alexpelletier/Library/Developer/Xcode/DerivedData/MyExpense-efnqzvoqwngzcmazaotyalepiice/Build/Products/Debug-iphoneos/MyExpense.app: errSecInternalComponent
Command /usr/bin/codesign failed with exit code 1
Open Keychain Access, then in the File menu select Lock All Keychains.
Then go back to Xcode and clean and rebuild. It will prompt you for your password again to unlock the keychain.
After this, assuming you have no other compile issues, it will succeed!
This occurs when the login keychain is locked. To unlock the login keychain, run:
security unlock-keychain login.keychain
If your keychain is password-protected, specify the password using the -p option:
security unlock-keychain -p PASSWORD login.keychain
If you're using a continuous integration system, you'll likely want to inject the password via an environment variable/token, which most CI systems offer in their settings.
The error code in question is described in Apple's docs as an internal error, so it's entirely possible this occurs in other cases too.
It seems like a bug in the code signing mechanism, restarting your mac should solve the problem
Had the same issue on High Sierra/Xcode 9.4.1, all attempts to sign ended in errSecInternalComponent
Go to Keychain Access
Go to the login keychain
Select the category "My Certificates"
Find the certificate you're signing with and expand it to see the key.
Double click the key
Go to the "Access control" tab.
Update key access control to "Allow all applications to access this item"
Alternatively:
run codesign command on mac terminal and "Always allow" /usr/bin/codesign access to key
If trying to sign from ssh/CI you also need to run
security unlock-keychain login.keychain
before trying to sign app bundle
I have met the same problem, I restart my macOS,and it works.
In China,we have a saying between developers:
Little problems,just restart.Big problems,should reinstall.
Sometimes,the above saying will greatly help you!
In case it helps someone else, I encountered an errSecInternalComponent error with codesign because I was running it over an ssh session to my macOS machine. Running the same command from a terminal window on the macOS machine itself worked.
Presumably this is because codesign needs access to the private key from the login keychain.
Running security unlock-keychain login.keychain (as explained by cbracken's answer) from the same session also should work.
As pointed out by #Equilibrium in one of the comments, if you are in command line env. like Jenkins(my case), you might need to pass the password to the security-unlock command mentioned in the solutions.
So instead of using,
security unlock-keychain login.keychain
use:
security unlock-keychain -p <login-keychain-password> <path-to-login-keychain>
where path-to-login keychain can be $HOME/Library/Keychains/login.keychain(my case) or simply login.keychain
for anyone that encountered this issue from jenkins and ssh:
high possibility that you have not granted access to the private key in keychain, i tried but not sure why all of these are not working:
security import .p12 file with -A or -T /usr/bin/codesign
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k #{password} #{keychainPath}
change all provisioning profile to [UUID].mobileprovision and copy them to '~/Library/MobileDevice/Provisioning\ Profiles' on jenkins server
clean derived data and reboot jenkins server
make sure default keychain is login keychain and unlocked it.
finally resolved by:
1.ssh [user]#[jenkinsServerIP] -L 5900:localhost:5900, log into jenkins server
2.open 'vnc://localhost'
this will launch a remote screen, if your jenkins server allow this...
then open keychain.app to grant access of /usr/bin/codesign to the private key
good luck
Nothing work for me from the above Solution.
Fallowing Solution Work for me...
First Open Keychain Access
Then Select Login And click Certificates
Double click Apple Worldwide Developer Relations Certificate Authority
Open trust section, and set to "Use System Defaults" from "Always Trust"
Clean the build folder and run
I ran security unlock-keychain login.keychain and my login password didn't work. So I rebooted, and then just ran Xcode again and it worked. Running the command works as well. Strange issue.
If trying to sign from ssh run command:
security unlock-keychain login.keychain
before trying to sign app bundle
or from UI
Update key access control to "Allow all applications to access this item"
Thx to #Equilibrium and #Jon McClung
I had the same issue Found out the problem is with code signing the app.
Opened the developer account and accepted the updated agreement and it worked.
Right clicking on the private key associated with the codesigning cert in the keychain, and then clicking on 'allow all applications' instead of relying on a prompt fixed it for me, since the build was happening via ssh.
I had to:
1) delete the certificate associated to the project
2) Back to the Xcode and revoke the app certificate
3) The Xcode require a new certificate
4) Lock all KeyChain
5) Clean the project
6) Rebuild
That's it. Hope it helps to anyone.
If you get errSecInternalComponent after
Warning: unable to build chain to self-signed root for signer …
, you might have the wrong Apple World Wide Developer Relations root certificate in your keychain. In this case, make sure that you import the WWDR certificate with which your developer certificate was signed. I imported the WWDR certificate expiring in 2023 and two hours later finally realized that it didn't work because my developer certificate had been signed with the WWDR certificate expiring in 2030 (AppleWWDRCAG3.cer). Download page: https://www.apple.com/certificateauthority/
Posting a work-around that we finally had to resort to, in case someone else is running out of things to try...
After installing a new Apple Distribution certificate in our "login" keychain, our Jenkins job suddenly started to fail singning iOS apps with the same errSecInternalComponent error:
Command /usr/bin/codesign failed with exit code 1
Our build pipeline calls security unlock-keychain, and we have no problems with our Enterprise Distribution cert (which was coincidentally updated and installed in the same Keychain just a few weeks prior), where the unlocking works as expected.
After trying all the usual things mentioned in this thread and elsewhere, we ended up running codesign manually as the Jenkins user in a new Terminal window, taking the exact same command as found in the Jenkins log: /usr/bin/codesign --force --sign...
This prompted entering the password to unlock the Keychain, which we did, and then selected "Always Allow".
After that Jenkins manages to sign (as expected).
This is obviously a bit of a work-around since we might have to do this again when the cert has expired, and it's really strange that unlocking works for Enterprise certs, but not the cert used for distributing through App Store... They literally share the same pipeline.
Just try it once using mac terminal but not from ssh session
security unlock-keychain login.keychain
And choose always allow in the prompted dialog.
And then you could xcodebuild in the remote session.
The above methods are useless to me.
I resoled it by:
Open keychain access.
Click Login Menu.
Remove all personal certificates.
Clean the project.
Rebuild.
That's it. Hope it helps to anyone.
In my case, this solved.
xcode -> preferences -> accounts -> select the account -> manage certificate -> (+) in bottom left -> Apple development
Ref: https://stackoverflow.com/a/62646138/234110
In my case BUCK was trying to sign the IPA for development, but there were not any development certificates installed. Changing the build config to release (this is what I needed - to build for iTunes) fixed it for me.
Just wanted to callout if someone face similar issue what I did. In my case my apple dev and distribution certificates, keys and provisioning profiles where upto date. My iOS code build was working in user mode without any issue however it does not work due to code sign issue when the code build runs with root privileges i.e. % sudo or invoking the Xcode using sudo through command line.
So, I copied the corresponding working certificates and keys the login to the system location in the keychain tool. Then it started working without any code sign issue.
Similarly, we can export the required certificates, keys for build from the working machine and import those into non working machine's keychain tool may solve the issue.
For me, I was able to sign files when using the Mac directly or via VNC, but not via ssh. I figured it must be something to do with access to the certificate within the keychain. I was already doing a security unlock-keychain [keychain name] but this didn't appear good enough.
What finally fixed it for me was (within a direct/VNC connection, not ssh):
Make sure the keychain in which your certificate resides is locked. Close Keychain Access.
Open Terminal
Do not run security unlock-keychain [keychain name].
Run a signing process using codesign tool. You will be challenged for a password to the keychain.
Enter the password and click "Always allow"
From now on I was able to use codesign via ssh, so long as I included security unlock-keychain [keychain name] before the command.
If you have a code signing certificate with the same name in the keychain, make sure you remove it. I had one which XCode reported as "Missing private key". I had to remove it via Keychain Access before the correct certificate was used by codesign.

Name of the Certificate/Authority who signed IPA [iOS]

Other question show how you can sign an already signed IPA, like this, or this. Specially this part is what interests me:
/usr/bin/codesign -f -s "iPhone Distribution: Certificate Name" --resource-rules "Payload/Application.app/ResourceRules.plist" "Payload/Application.app"
Once I have the re-signed ipa, how can I see/know that in fact the IPA I currently have has been signed by "iPhone Distribution: Certificate Name"?
codesign -d -vvvv /path/to/The.app
-d for displaying signature info, lots of vs for lots of verbosity.
I don't know if its the best way. By using Terminal you can browse the contents of signed ipa file. Change the extension to zip and extract it. Then try browsing to following path >Payload/AppName.app/embedded.mobileprovision.
You can copy the embedded.mobileprovision to some other location and open in text editor to see the details.
To my knowledge, 'codesign' do not have any option to actually check that the resigning of the app is ok.
Actually, it can go wrong for many reasons (entitlements, provisioning, id mismatch ...).
The only way to check is to install the IPA (via Xcode, iPhone Configurator or iTunes if no other choice) on a device and see if the app launches.

Resources