Signing and Notarizing with GitHub Actions¶
The indygreg/apple-code-sign-action
GitHub Action provides a relatively turnkey way to sign and notarize using
rcodesign
.
Signing¶
You will need to make a signing certificate available to GitHub Actions.
You can either install the signing certificate locally in the GitHub Actions runner/workflow or you can use the Remote Code Signing feature.
Local Certificate Signing¶
There are multiple ways to make a local code signing certificate available to GitHub Actions. Each have various security / convenience trade-offs.
We recommend storing the certificate private key in a GitHub Actions Secret. Storing the private key this way prevents offline attacks.
Find the PEM representation of your signing certificate. It will look something like:
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCkdCzwAgHcNbpH
awCPZISFqL6vPHstX1F9FjjGiOqQZ60xtXMsj1vpfxhpBZwxO/Q3RDn1ogvCluE5
...
-----END PRIVATE KEY-----
Use the instructions at https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions#creating-secrets-for-a-repository to create a secret with this private key content.
Assuming the secret is named PRIVATE_KEY
, you can write the private key to
a file and pass it to the GitHub Action doing something like the following:
steps:
- name: Write PEM encoded private key data to a file
env:
PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}
run: |
echo $PRIVATE_KEY | tr ' ' '\n' > key.pem
- name: Code signing
uses: indygreg/apple-code-sign-action@v1
with:
pem_file: |
key.pem
cert.pem
Remote Signing¶
In remote signing mode, a remote machine has access to the code signing certificate so that GitHub Actions never has access to it. This is theoretically more secure since if GitHub gets hacked, nobody has an offline copy of your signing certificate!
See Session Agreement for an overview of the mechanisms for initiating remote signing.
We recommend use of public key agreement over shared secrets because it should be more secure.
You can even use your code signing certificate’s public key as the public key to use.
steps:
- name: Code signing
uses: indygreg/apple-code-sign-action@v1
with:
remote_sign_public_key: |
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt2CB7Q9oBDpA6Pkd4spG
CWF+LbOnJUGkUPeCn7frIv8CT6HMxaCE8KokTuNo8nVqJW9Ocy/oFHO2SiJ0H2EM
FgaWIVgfiJuZKIMwzDzIEtgV48VE9V+9ARaI5JOFm+buivAtlCdTzpUASscIqVb1
00Lqyf8oAd679bywsxEyigVTxAFQ+qHFfyk0/D8Z8tg7e+osoXAFoH/E6fdKaUMv
EUwoMvpulvT/+gqAS9qnnYd2ugbHNtjIrD1YK5JF5oi2JePDS37uF4QmuEXGAh3e
DlIRDozAqC0Oeg0zPVuFBFZy1iVy4NS8aYY9NiaKH3EMDVkzz077znw/cJp9+wHZ
WQIDAQAB
Notarizing¶
Notarizing requires you to have an App Store Connect API Key.
Follow the instructions at Obtaining an App Store Connect API Key.
Assuming you ran rcodesign encode-app-store-connect-api-key
to obtain a
unified JSON file, we recommend copying that JSON data into a GitHub Actions
secret.
Then simply write out that secret to a file and reference it from the GitHub Actions config:
steps:
- name: Write API Key to file
env:
API_KEY: ${{ secrets.APP_STORE_API_KEY }}
run: echo $API_KEY > app_store_key.json
- name: Notarize
uses: indygreg/apple-code-sign-action@v1
with:
app_store_connect_api_key_json_file: app_store_key.json
# Remember to enable notarization and to disable signing if you just
# want to notarize.
sign: false
notarize: true
staple: true
input_path: MyApp.app