Wait, what is code signing? Code signing is required on iOS when distributing your app to customers. It assures that your app can be trusted and hasn’t been modified since it was last signed.
See Apple’s docs for more general details on code signing.
When deploying an app to the App Store, a beta testing service or even installing it on a single device, most development teams have separate code signing identities for every member. This results in dozens of profiles including a lot of duplicates.
You have to manually renew and download the latest set of provisioning profiles every time you add a new device or a certificate expires. Additionally this requires spending a lot of time when setting up a new machine that will build your app.
What if there was a central place where your code signing identity and profiles are kept, so anyone can access them during the build process? This way, your entire team can use the same account and have one code signing identity without any manual work or confusion.
Instead of registering for yet another service, you can use a separate private Git repo to sync your profiles across multiple machines.
The basic requirement is to have one code signing identity shared across your team. The easiest way to do that is to create a new Apple ID for the team (e.g. email@example.com) and use that from now on. To get started:
1. First, create a new, private Git repo in which you can store the profiles.
2. Next, create a new private key and certificate for each environment, such as “Distribution” and “Development”. Then store these private keys and certificates in your Git repo.
3. Then, create a new provisioning profiles for the various targets, such as “Development”, “App Store” and “Ad hoc” with the matching certificates and store these in your Git repo.
4. Before committing the files to Git, it is recommended to encrypt those files (e.g. using openssl).
5. Now, each of your machines can access the Git repo and install the latest certificate and provisioning profiles: - The certificates and private keys should be imported into your Keychain, either using Finder or using the 'security import' command - The provisioning profiles should be copied over to '~/Library/MobileDevice/Provisioning\ Profiles/'
6. Your Xcode project must be configured to choose the provisioning profiles automatically or define it statically. The ideal solution is to pass the UUID of the provisioning profile, via an environment variable, for each of your bundle identifiers.
In the future, when you add a new device to your Ad Hoc or Development provisioning profile, you can update the profile in your Git repo.
Make sure the provisioning profile is created using the correct certificate
If your app has multiple targets (e.g. Today widget) you have to repeat the above for each target
Don’t set the provisioning profile in your Xcode project to Automatic, as it doesn’t always select the correct profile
Both your keys and provisioning profiles are encrypted using OpenSSL using a passphrase.
Storing your private keys in a Git repo may sound off-putting at first. We did an in-depth analysis of potential security issues and came to the following conclusion:
What could happen if someone stole a private key?
If attackers would have your certificate and provisioning profile, they could codesign an application with the same bundle identifier.
What's the worst that could happen for each of the profile types?
App Store Profiles
An App Store profile can't be used for anything as long as it's not re-signed by Apple. The only way to get an app resigned is to submit an app for review (which takes around 7 days). Attackers could only submit an app for review, if they also got access to your iTunes Connect credentials (which are not stored in Git, but in your local keychain). Additionally you get an email notification every time a build gets uploaded to cancel the submission even before your app gets into the review stage.
Development and Ad Hoc Profiles
In general those profiles are harmless as they can only be used to install a signed application on a small subset of devices. To add new devices, the attacker would also need your Apple Developer Portal credentials (which are not stored in Git, but in your local keychain).
Attackers could use an In-House profile to distribute signed application to a potentially unlimited number of devices. All this would run under your company name and it could eventually lead to Apple revoking your In-House account. However it is very easy to revoke a certificate to remotely break the app on all devices.
Because of the potentially dangerous nature of In-House profiles we decided to not allow the use of match with enterprise accounts.
To sum up
You have full control over the access list of your Git repo, no third party service involved
Even if your certificates are leaked, they can't be used to cause any harm without your iTunes Connect login credentials
Match does not currently support In-House Enterprise profiles as they are harder to control
If you use GitHub or Bitbucket we encourage enabling 2 factor authentication for all accounts that have access to the certificates repo
Generates your code signing identity and provisioning profiles if necessary.
Stores all certificates and provisioning profiles in a separate Git repository.
Automatically installs the certificates and provisioning profiles from the repository.
To get started, create a new private Git repo and run:
To generate and store new certificates and provisioning profiles run:
On a new machine, just run match appstore to install the existing certificates.
If you never really cared about code signing and have a messy Apple Developer account with a lot of invalid, expired or Xcode managed profiles/certificates, you can use the match nuke command to completely clear your developer portal.
This command will revoke all certificates and provisioning profiles for a specific environment.