fastlane-plugin-voip_push_certificate

Test

Create and renew Apple VoIP Services push certificates (the certificate type PushKit requires) from a fastlane lane.

fastlane's built-in get_push_certificate (pem) handles development, production and website push certificates, but not VoIP ones. This plugin fills that gap using the same Spaceship APIs, so it behaves the way you already expect pem to behave.

Getting Started

Requires Ruby 3.1 or newer.

Add the plugin to your project:

fastlane add_plugin voip_push_certificate

Or, to use it straight from source without installing the gem, add this to your fastlane/Pluginfile:

gem 'fastlane-plugin-voip_push_certificate', git: 'https://github.com/Rafinha-rf/fastlane-plugin-voip_push_certificate'

Usage

lane :renew_voip do
  get_voip_push_certificate(
    app_identifier: "com.example.app",
    output_path: "./certs"
  )
end

By default this creates voip_com.example.app.pem and voip_com.example.app.p12 (plus the private key) in output_path, but only if the current certificate expires within 30 days. Otherwise it logs how long the existing one is still valid and does nothing.

The action returns the path to the generated .pem, or nil when the existing certificate was kept. All generated paths are also exposed through the lane context:

lane_context[SharedValues::VOIP_PUSH_CERTIFICATE_PEM_PATH]
lane_context[SharedValues::VOIP_PUSH_CERTIFICATE_P12_PATH]
lane_context[SharedValues::VOIP_PUSH_CERTIFICATE_PKEY_PATH]
lane_context[SharedValues::VOIP_PUSH_CERTIFICATE_CER_PATH]

Options

Option Type Default Description
app_identifier String from Appfile The bundle identifier of your app
username String from Appfile Your Apple ID username
team_id String from Appfile Developer Portal team ID, if you're in multiple teams
team_name String from Appfile Developer Portal team name, if you're in multiple teams
active_days_limit Integer 30 Renew only if the current certificate expires within this many days
force Boolean false Create a new certificate even if the current one is still valid
revoke_existing Boolean false Revoke the matching certificate before creating a new one. See the warning below
generate_p12 Boolean true Also write a .p12 file
p12_password String none Password for the .p12 file
save_private_key Boolean true Also write the private key as a .pkey file
save_cer Boolean false Also write the raw DER certificate as a .cer file
bag_attributes Boolean false Write the .pem with OpenSSL bag attributes. See below
pem_name String voip_<app_identifier> Base file name for the generated files
output_path String . Directory to write the certificates into

Every option also has an environment variable, e.g. VOIP_PUSH_CERTIFICATE_APP_IDENTIFIER.

Things worth knowing

There is no development/production distinction

Apple issues a single VoIP Services certificate that is valid for both the sandbox and the production APNs environments. That is why, unlike get_push_certificate, this action has no development option.

Revoking is opt-in, on purpose

Apple allows at most two active VoIP certificates per App ID. When that limit is reached the action fails with an explanation rather than revoking anything, because revoking a certificate immediately stops every push provider still using it, including your production one.

Set revoke_existing: true only when you are sure nothing depends on the old certificate:

get_voip_push_certificate(
  app_identifier: "com.example.app",
  force: true,
  revoke_existing: true
)

The bag_attributes option

Some push providers reject a plain concatenated PEM and expect the format that openssl pkcs12 -nodes produces, with friendlyName and localKeyID headers around each block. If yours does, set bag_attributes: true. The default (false) matches what get_push_certificate writes: the certificate followed by the private key, nothing else.

Authentication

This uses Spaceship's Apple Developer Portal API, which needs an Apple ID and password:

export FASTLANE_USER="you@example.com"
export FASTLANE_PASSWORD="…"

Two-factor authentication is supported through fastlane's usual session mechanism (FASTLANE_SESSION, fastlane spaceauth).

App Store Connect API keys are not supported. Apple's App Store Connect API does not cover push certificates, so the portal API is the only option. This is a limitation of Apple's API, not of this plugin. get_push_certificate has exactly the same constraint.

Running tests

bundle install
bundle exec rake

Relationship to fastlane

This is an unofficial plugin and is not affiliated with fastlane or Apple. Adding VoIP support to pem itself has been requested since 2017 in fastlane/fastlane#8145; if it ever lands upstream, this plugin will be deprecated in favour of it.

License

MIT. See LICENSE.