fastlane: App Store distribution certificate expiring

New Issue Checklist

Issue Description

I use match to manage my certs and profiles. What should I do when my App Store distribution certificate is about to expire?

Before Fastlane:

  • Create a new certificate
  • Create a new profile with the certificate

With Fastlane:

  • Once the old certificate expires will match automatically create a new cert and recreate the profiles?
  • Is there a way I can create a new certificate and update my profiles before the old certificate expires without having to resort to fastlane nuke distribution or manually editing the repo?
đŸš« fastlane environment đŸš«

Stack

Key Value
OS 10.13.1
Ruby 2.3.4
Bundler? true
Git git version 2.14.1
Installation Source ~/.rvm/gems/ruby-2.3.4/bin/fastlane
Host Mac OS X 10.13.1 (17B46a)
Ruby Lib Dir ~/.rvm/rubies/ruby-2.3.4/lib
OpenSSL Version OpenSSL 1.0.2l 25 May 2017
Is contained false
Is homebrew false
Is installed via Fabric.app false
Xcode Path /Applications/Xcode.app/Contents/Developer/
Xcode Version 9.0.1

System Locale

Variable Value
LANG en_US.UTF-8 ✅
LC_ALL
LANGUAGE

fastlane files:

`./fastlane/Fastfile`
# Customise this file, documentation can be found here:
# https://github.com/fastlane/fastlane/tree/master/fastlane/docs
# All available actions: https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Actions.md
# can also be listed using the `fastlane actions` command

# Change the syntax highlighting to Ruby
# All lines starting with a # are ignored when running `fastlane`

# This is the minimum version number required.
# Update this, if you use features of a newer version
fastlane_version "2.61.0"

# Required Xcode version
required_xcode_version = "9.0.1"

fastlane gems

Gem Version Update-Status
fastlane 2.61.0 đŸš« Update available

Loaded fastlane plugins:

No plugins Loaded

Loaded gems
Gem Version
did_you_mean 1.0.0
executable-hooks 1.3.2
bundler-unload 1.0.2
rubygems-bundler 1.4.4
bundler 1.15.4
io-console 0.4.5
rake 12.1.0
CFPropertyList 2.3.5
public_suffix 2.0.5
addressable 2.5.2
babosa 1.0.2
claide 1.0.2
colored2 3.1.2
cork 0.3.0
nap 1.1.0
open4 1.3.4
claide-plugins 0.9.2
colored 1.2
highline 1.7.8
commander-fastlane 4.4.5
daemons 1.2.4
multipart-post 2.0.0
faraday 0.13.1
faraday-http-cache 1.3.1
git 1.3.0
kramdown 1.15.0
no_proxy_fix 0.1.1
sawyer 0.8.1
octokit 4.7.0
unicode-display_width 1.3.0
terminal-table 1.8.0
danger 5.5.3
thor 0.20.0
danger-swiftlint 0.10.1
declarative 0.0.10
declarative-option 0.1.0
unf_ext 0.0.7.4
unf 0.1.4
domain_name 0.5.20170404
dotenv 2.2.1
eventmachine 1.2.5
excon 0.59.0
http-cookie 1.0.3
faraday-cookie_jar 0.0.6
faraday_middleware 0.12.2
fastimage 2.1.0
gh_inspector 1.0.3
jwt 1.5.6
little-plugger 1.1.4
multi_json 1.12.2
logging 2.2.2
memoist 0.16.0
os 0.9.6
signet 0.8.1
googleauth 0.5.3
httpclient 2.8.3
mime-types-data 3.2016.0521
mime-types 3.1
uber 0.1.0
representable 3.0.4
retriable 3.1.1
google-api-client 0.13.6
json 2.1.0
mini_magick 4.5.1
multi_xml 0.6.0
plist 3.3.0
rubyzip 1.2.1
security 0.1.3
slack-notifier 1.5.1
terminal-notifier 1.8.0
tty-screen 0.5.0
word_wrap 1.0.0
nanaimo 0.2.3
xcodeproj 1.5.2
rouge 2.0.7
xcpretty 0.2.8
xcpretty-travis-formatter 0.0.4
mustermann 1.0.1
rack 2.0.3
rack-protection 2.0.0
tilt 2.0.8
sinatra 2.0.0
thin 1.7.2
webrick 1.3.1
xcode-install 2.3.1

generated on: 2017-10-27

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 17
  • Comments: 58 (11 by maintainers)

Most upvoted comments

This is still an issue, can people who find this interesting please add a thumbs up so this can get more attention?

Just wanted to chime in here (again)! I would also like to have this feature ❀ fastlane is the best way (only way IMO) to manage certs and profiles. The hard part about developing this feature is getting an expired certificate and being to test against. I don’t think there is a way for us to manually expire cert so it requires waiting for an account’s cert to expire (which I currently do not have any). Once that cert is expired, we can’t really test any if this new implementation we write a lot of times because that cert will be deleted 😕

One possible solution that we could possibly make I guess might be to add an option called something like create_new_cert_num_days_before_expiration: 30 (looking for a better name) that will could look when the cert is going to expire, delete it, create a new one, and create new profiles? đŸ€”đŸ€”đŸ€”đŸ€”đŸ€”đŸ€”

Doing this approach would make it easier to test because I could set my option to 900 days and then everyone could delete (expire) their cert however many days for their own workflow.

Any thoughts / objections / issues to an approach like this?

Heyyyy 👋 I totes understand this issue. When match tries to create a new profile, it will first try to create a new profile for that app identifier from the existing cert that app was using (almost like its recreating) <-- this is why nuking solves this issue.

However, I do agree that there should almost be some sort of mini-nuke on a single provisioning profile so that the newly created profile will be used from the newest cert. <-- I will look into this issue

I would also like to fix the App Store expiring issue but that one is a bit harder to test since I can’t manually expire a certificate on the iOS Developer Center 😱

Hey @krish722, I got the same error as @agordeev:

“Your certificate ‘XXXXXXXXXX.cer’ is not valid, please check end date and renew it if necessary”

It’s the certificate that expired, not the profile. I know how to delete everything manually from the repos and regenerate them. But it would be so much convenient to have fastlane do it, which I’m guessing that’s why everybody uses it, not to do manual stuff

Thanks!

This issue will be auto-closed because there hasn’t been any activity for a few months. Feel free to open a new one if you still experience this problem 👍

Just stumbled onto this thread
 Our prod profile is about to expire. Seems crazy to have to let it expire and then run fastlane match to generate a new one
 +1 for an option to renew prior to expiration. What is the correct way to handle this without having to manually decrypt and edit the match repo?

This definitely needs a better solution. I can’t use nuke because I have other apps/certificates using the same repo.

And waiting for the certificate to expire is not very safe. We are missing a lot of days to prepare a new build with the new certificate.

This might not be a big problem with App Store apps, since they still work even if a certificate expires. But with enterprise apps, once the certificate expires, the app stops working.

A similar issue is mentioned here for the need to delete individual certificates from a repo: #10502

@CihanBoz Correct, it throws an error because match doesn’t really know (right now) if it was revoked manually by someone, expired, or if some other error occurred. match prompts for the error because it doesn’t want to do anything unknown/dangerous to the user and their certs

That being said
 I think we could create an option to recreate cert (mini nuke) if something like this occurs (so that its at least somewhat opt-in). Thoughts on that?

My workflow after I receive 30 days expiration notification from Apple (tried on dev and appstore certs):

  1. Remove certs and profiles from repo
  2. Revoke profiles from Dev Portal
  3. Run match to regenerate everything

I guess in case of already expired certs it will be:

  1. Remove certs and profiles from repo
  2. Run match to regenerate everything

It would be really nice to have this automated by match, like it is now with push certs. If expiration date is less, than N days - do the way I described.

The only way I found to do this right now is to manually update the profile/certificate in the git repo:

  1. Launch irb in your terminal and run the following:
require 'match'
git_url = '<url to your git repo, you can find this in your Matchfile>'
workspace = Match::GitHelper.clone(git_url, false)

Don’t close IRB yet, copy the workspace directory path

  1. Run open <workspace directory> so it opens in finder on your machine`
  2. Replace your .cer and .p12 files inside the certs folder, the .p12 should be just the key exported with no password on it (make sure it has identical name as before)
  3. Replace your provisioning profile inside the profiles folder (make sure it has identical name as before)
  4. Return to IRB and run Match::GitHelper.commit_changes(workspace, "Manual Update", git_url)
  5. Run fastlane match <env>

This should be built into fastlane match as an option, nuking stuff from the program portal just to renew profiles is extremely dangerous as for enterprise deployments can disable the app and we have to renew these and push updates before the old profiles expire.

A possible solution to force Fastlane match to stop using the certificate that is about to expire is to remove manually the certificate and the private key from the fastlane repo. This is similar to @oanhof. This should force match to create new iOS Distribution certificate and use it to generate provisionings further. The old non-expired certificate will remain active until expiration. So all Enterprise apps will continue to work. But you will have time to resign these apps with the new provisioning and notify the users that the app needs to be updated.

I will test this tomorrow. From my experience with ‘match’ so far it seems that should work!

@ohayon I can run fastlane match nuke distribution but I’m looking for an alternative. An expiring distribution cert is something most users will encounter once a year. I’m wondering what to do when that happens.

  • Do I wait until the cert expires and then run fastlane match appstore --force. Will that automatically create a new cert if the old one is expired?
  • Do I have to run fastlane match nuke distribution every year?

@joshdholtz First of all, thank you for looking into it!

I would also like to fix the App Store expiring issue but that one is a bit harder to test since I can’t manually expire a certificate on the iOS Developer Center

When an certificate expires IMHO it just disappears from the Dev Center, it is the same behaviour like when you press “revoke” manually. So if match doesn’t find the certificate anymore in the Dev Center it could/should create a new one. If I remember correctly the current behaviour of match is to throw an error that the certificate is not in the Dev Center and that is it, right?

Just to mention that the approach described by me above is working fine.

Fastlane always saves a lot of time and it’s almost perfect. But I still hope these hiccups can get fixed or improved. I just solved it by manually deleting my debug certs and profiles for my app. I can’t use nuke because I also have many certs and profiles for other apps on it. There’s also the fact I don’t like manually touching something that has been entirely generated by some system, as it is the case with the fastlane match repo.

+1

It’s a shame that fastlane offers match but fails to handle expiring certificates without forcing the user to nuke or manually editing the repo, as previously also documented in #10395 and #10076. Would be really great to see this improved and even better to allow preemptively creating new certificates before they expire.

I have done some work and did a work around my side.

Basically problem with fastlane is not getting expired profile in the list at all.

Spaceship.provisioning_profile.all

Never gives expired profile. It can get invalid profile but not expired.

If this is fixed then the existing code will work.

How its working now.

  1. when certificate expires in developer portal. that is automatically removed in dev portal.
  2. profile expired in dev portal but not removed.
  3. Run match now.
  4. creates the new certificate.
  5. tying to create profile with AppStore_bundleid. where expired profile preset in dev portal. so getting this error error respone - {“responseId”=>“22222222-33333-4335-a1bc-ce2269bb9153”, “resultCode”=>35, “resultString”=>“There were errors in the data supplied. Please correct and re-submit.”, “userString”=>“Multiple profiles found with the name ‘match AppStore com.example.mobile’. Please remove the duplicate profiles and try again.”, “creationTimestamp”=>“2019-01-08T19:53:38Z”, “protocolVersion”=>“QH6333”, “userLocale”=>“en_US”, “requestUrl”=>“url
”, “httpCode”=>200, “validationMessages”=>[{“validationKey”=>“provisioningProfileName”, “validationUserMessage”=>“Multiple profiles found with the name ‘match AppStore com.example.mobile’. Please remove the duplicate profiles and try again.”}]}
  6. Also now match did clears the storage
 so p12 is not checked in too.

My work around is generate a new name that can be created.

Fix needed is expired profile should be accessible.

@joshdholtz That sounds like a great suggestion and it would be backwards compatible as well 👍

@BObereder Just had the same problem. Fixed it by manually deleting the expired certificate from our match git repository and running fastlane match appstore again.