Skip to content

[match] Restore renew expired certs (opt in)#30096

Merged
iBotPeaches merged 7 commits into
fastlane:masterfrom
OdNairy:restore-renew-expired-certs-21691
Jun 28, 2026
Merged

[match] Restore renew expired certs (opt in)#30096
iBotPeaches merged 7 commits into
fastlane:masterfrom
OdNairy:restore-renew-expired-certs-21691

Conversation

@OdNairy

@OdNairy OdNairy commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Checklist

  • I've run bundle exec rspec from the root directory to see all new and existing tests pass
  • I've followed the fastlane code style and run bundle exec rubocop -a to ensure the code style is valid
  • I see several green ci/circleci builds in the "All checks have passed" section of my PR (connect CircleCI to GitHub if not)
  • I've read the Contribution Guidelines
  • I've updated the documentation if necessary.
  • I've added or updated relevant unit tests.

Motivation and Context

Re-enable expired certificate renewal in fastlane match commands.
It was originally implemented in #21691 but turned off soon in #21812 in favor of #21809. The idea of #21809 was to implement a more intelligent and broad support for automatic renewal. It was January, 2024 and the PR stalling since February, 2024.

According to #21848 this issue has quite a demand and it is better to bring it back even without ideal implementation.

Resolves #21848

Description

Re-introduce renew_expired_certs option (default: false) to renew certificates during the fastlane match [development|distribution|etc]. Current implementation finds the first certificate matching requested type, checks the expiration date.
The expired cert is removed from match storage and a new one is generated, but the old certificate is not revoked on the Apple Developer Portal.

Testing Steps

bundle exec rspec match/spec/runner_spec.rb

New regression specs:

  • renews an outdated certificate — invalid stored cert is deleted (.cer + .p12), a new one is generated, and both file additions/deletions are committed to storage.
  • does not renew an outdated certificate in readonly mode even when renew_expired_certs is true — readonly run leaves storage untouched and raises the "certificate is not valid" error instead.
  • does not renew an outdated developer_id certificate when authenticated with an App Store Connect API token — developer_id cert is neither deleted nor regenerated when only an API token is available.

OdNairy and others added 6 commits June 25, 2026 15:57
Re-enables automatic renewal of expired certificates that was disabled by
the hotfix in fastlane#21812. Keeps the readonly guard and certificate_id changes
that landed afterwards.
Brings back the 'renews an outdated certificate' test and the
renew_expired_certs option in related specs. Adds a regression test
ensuring an outdated certificate is not renewed in readonly mode even
when renew_expired_certs is true.
Even when renew_expired_certs is true, match must not delete/regenerate a
stored certificate when:
- running in readonly mode
- the cert is a developer_id type authenticated with an App Store Connect
  API token (account holder login is required for renewal via API)
…ificate

Document that the old certificate is only removed from match storage, not
revoked on the Apple Developer Portal, and point to `match nuke` for
freeing up certificate slots.
@OdNairy OdNairy marked this pull request as ready for review June 25, 2026 20:10
@iBotPeaches

Copy link
Copy Markdown
Member

Trying to make sense of the history here & thanks for booting this back up. I for sure hate having to manually surgically remove an expired cert every year or so from my own match storage.

So roughy:

  • It was added - reverted quickly, but I can't find a large reason why outside of a different implementation
  • This adds it back with no changes and still as the default

I think if this is coming back - it has to be opt-in till we figure out what caused its removal. Probably deletion is such a scary aspect, but knowing we don't touch the Apple side is probably safer, but adapting match to not selecting an expired cert does seem preferred.

@OdNairy

OdNairy commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @iBotPeaches for taking an attention
I believe the reason is in this comment:

Well if that removes the just freshly added renew_expired_certs option, we need to either remove the previous PR before making a new release, or delay the release until we land this one, right?

From my understanding, the original (#21691) implementation was waiting to be included in the next release.
But then @lacostej noticed that the new iteration of the feature will come in the next release and will remove recently-added option renew_expired_certs.
And since it doesn't make sense to introduce the new option just for a one release if you already know that it will gone soon, it makes sense to remove the option already and just wait a bit longer.

Unfortunately, it happened that the new version never been completed and fastlane users didn't get an option to renew certificate in any release

@OdNairy

OdNairy commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

Timeline:

December, 2023

  1. Nekrich opened a pull request [match][sigh] add option to automatically renew expired certificates (defaults to enabled) #21691 to automatically renew certificate. This include a new option renew_expired_certs (defaults true)

January, 2024

  1. Original PR was merged after some merge conflicts.

  2. The next day after the merge nekrich opens a new draft pull request to address a multiple certificates and developer_id cert issue: [match] select cert with the most furthest expiration date in the future #21809

  3. The same day lacostej highlights removal of a new option renew_expired_certs introduced in the original pr:

    Well if that removes the just freshly added renew_expired_certs option, we need to either remove the previous PR before making a new release, or delay the release until we land this one, right?

  4. Nekrich responds

    I can create a small PR that removes the option, but the logic stays the same. Give me a couple of mins

    and creates [match][hotfix] remove the renew_expired_certs option introduced in #21691 and revert the default behavior while we address issues with it #21812

February, 2024

  1. Nekrich faces some encryption related issues and assuming that it might potentially be related to the original pull request. And that's why it might worth to disable automatic renewal completely.
  2. Lacostej assumed that it actually could be related to the [match] improve encryption internals, solving flaky test (#21663) #21790 he was working recently. This is the one that introduced a new encryption algo but wasn't fully backward compatible until a bit later a new flag was introduced.
  3. Next lacostej summarizing a plan to remove the renew_expired_certs option while nekrich continue working on the draft PR. Also lacostej approves the PR [match][hotfix] remove the renew_expired_certs option introduced in #21691 and revert the default behavior while we address issues with it #21812 and next day it was merged

And this is where the story ends

@OdNairy

OdNairy commented Jun 26, 2026

Copy link
Copy Markdown
Contributor Author

FYI: I've confirmed a new default behaviour in two scenarios:

  1. Execute with valid certificate
  2. Execute with expired certificate and watch it update cert and provisions

@iBotPeaches

Copy link
Copy Markdown
Member

thanks. I'm thinking we roll with it off then. I'd rather get a release or two of people opting into it and testing out this code that has been dormant for weeks vs defaulting it on especially with deletion involved.

@OdNairy

OdNairy commented Jun 27, 2026

Copy link
Copy Markdown
Contributor Author

Fair enough
I already changed the default behavior to false.

Im going to renew distribution certificates on my job 11th of July. So I'm gonna test automation with production data.
Wanna highlight that this is extremely important that we never revoke distribution certificates in this feature. If you are shipping signed XCFrameworks and gonna revoke certificates before it will expire, you will end up with every build job of your customers be broken due to invalid signature. Yes, this happened to me last yeah 😅 so this yeah I would like to have a proper solution.

@iBotPeaches is there anything else to proceed with review?

@iBotPeaches iBotPeaches changed the title Restore renew expired certs 21691 [match] Restore renew expired certs (opt in) Jun 27, 2026
@iBotPeaches

Copy link
Copy Markdown
Member

Are you saying its already hardened to have greater care on those cert types? I only build React Native & Flutter so don't have experience signing XC's or the renewal process for that.

Generally only do pass keys, push notification keys and the regular ole profiles & certs for mobile apps.

@OdNairy

OdNairy commented Jun 27, 2026

Copy link
Copy Markdown
Contributor Author

Yes. The great thing about this feature is that never tries to revoke certificate on the Apple portal which could cause a lot of damage to SDK developers.
The worst could happen – is the certificate removal from match storage + issue a new certificate.
However, this wouldn't happen until the certificate in storage is expired already.

So we could try a safer approach with false default first and switch it to true when we confirm in practice that it's reliable

@iBotPeaches iBotPeaches left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm open to trying this as an opt-in, because like you. Every year I have to manually delete some certs out of my repo so match can continue.

At some point we may learn this is not preferred over match just selecting a cert with a date further out, but that day is not today.

@OdNairy

OdNairy commented Jun 28, 2026

Copy link
Copy Markdown
Contributor Author

Ok, so what is the following process? I don't have permissions to merge this pull request. Could you merge it or there is still smth missing?

@iBotPeaches iBotPeaches merged commit 20f68fd into fastlane:master Jun 28, 2026
12 checks passed

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @OdNairy 👋

Thank you for your contribution to fastlane and congrats on getting this pull request merged 🎉
The code change now lives in the master branch, however it wasn't released to RubyGems yet.
We usually ship about once a month, and your PR will be included in the next one.

Please let us know if this change requires an immediate release by adding a comment here 👍
We'll notify you once we shipped a new release with your changes 🚀"

mapbox-github-ci-writer-public-1 Bot pushed a commit to mapbox/mapbox-maps-ios that referenced this pull request Jun 30, 2026
<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## Summary

Closes security findings for `faraday` (CVE-2026-54297) and `excon`
(CVE-2026-54171) in `projects/maps-ios/mapbox-maps-ios/Gemfile`.

| CVE | Package | Fix |
|-----|---------|-----|
| CVE-2026-54297 | faraday | `~> 1.10.6` |
| CVE-2026-54171 | excon | `>= 1.5.0` |

## Changes

- Bump `faraday` from `1.10.5` → `1.10.6` (patched NestedParamsEncoder
depth limit).
- Pin `excon` to `>= 1.5.0` (patched redirect header redaction).
- Source `fastlane` from git ref
[`20f68fd`](fastlane/fastlane@20f68fd)
until a RubyGems release ships the required dependency updates. This
commit includes:
- Relaxed `excon` upper bound (`< 2.0.0`) for CVE-2026-54171 —
[fastlane#30085](fastlane/fastlane#30085)
- Match expired certificate renewal (opt-in) —
[fastlane#30096](fastlane/fastlane#30096)

## Note on `debug-env/Gemfile`

The security scanner also reports `debug-env/Gemfile`, but that
directory was removed in #5159. Only `mapbox-maps-ios/Gemfile` exists in
the tree today.

## Follow-up

Once fastlane releases a version that includes both fixes, revert the
git pin back to `gem "fastlane", ">= 2.232.1"` from RubyGems and refresh
the lockfile.

## Testing

- `bundle install` succeeds with the updated lockfile.
- Resolved versions: `faraday 1.10.6`, `excon 1.5.0`, `fastlane 2.236.1`
(from git @ `20f68fd`).
<!-- CURSOR_AGENT_PR_BODY_END -->

<div><a
href="https://cursor.com/agents/bc-3316d43f-2079-48e1-9ae7-4cb4417b58e5"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/background-agent?bcId=bc-3316d43f-2079-48e1-9ae7-4cb4417b58e5"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img
alt="Open in Cursor" width="131" height="28"
src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>

cc @mapbox/maps-ios

---------

Co-authored-by: Cursor Agent <[email protected]>
GitOrigin-RevId: 13fefda61fa901212bf218f5f408a2e1c28d7f96
This was referenced Jul 4, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Congratulations! 🎉 This was released as part of fastlane 2.237.0 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[match] doesn't renew expired certificate automatically

2 participants