如何在 Github Actions 的 macOS runner 中签署和公证一个 PKG?

4

背景

我正在构建一个Github Actions作业,用于构建、签名和公证一个PKG文件。

我使用了一个Apple Id账户(工作流需要用户名和密码),以及一个带私钥的开发者ID安装器证书(加密)。这两个都保存为secrets(base64),并将在工作流中转换为.p12文件,然后添加到钥匙串中。

这个作业是私有存储库中更大工作流的一部分,该工作流首先从软件中生成文件(使用Pyinstaller),然后在AWS S3 Bucket上导出PKG。

实施

jobs:
  [...]

  pkg:
    needs: [...]
    runs-on: macos-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Download macos bin file
        uses: actions/download-artifact@v2
        with:
          name: macos-bin-files
          path: dist/
      - name:
        run: | 
          ----- Create certificate files from secrets base64 -----
          echo ${{ secrets.DEVELOPER_ID_INSTALLER_CER }} | base64 --decode > certificate_installer.cer
          echo ${{ secrets.DEVELOPER_ID_INSTALLER_KEY }} | base64 --decode > certificate_installer.key

          ----- Create p12 file -----
          openssl pkcs12 -export -name zup -in certificate_installer.cer -inkey certificate_installer.key -passin pass:${{ secrets.KEY_PASSWORD }} -out certificate_installer.p12 -passout pass:${{ secrets.P12_PASSWORD }}

          ----- Configure Keychain -----
          KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
          security create-keychain -p "${{ secrets.KEYCHAIN_PASSWORD }}" $KEYCHAIN_PATH
          security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
          security unlock-keychain -p "${{ secrets.KEYCHAIN_PASSWORD }}" $KEYCHAIN_PATH

          ----- Import certificates on Keychain -----
          security import certificate_installer.p12 -P "${{ secrets.P12_PASSWORD }}" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
          security list-keychain -d user -s $KEYCHAIN_PATH

          ----- Generate PKG from files -----
          use a macos installer script (ref: https://github.com/KosalaHerath/macos-installer-builder/tree/master/macOS-x64)

          ----- Sign PKG file -----
          productsign --sign "${{ secrets.DEVELOPER_ID_INSTALLER_NAME }}" $INPUT_FILE_PATH $OUTPUT_FILE_PATH

          - name: "Notarize Release Build PKG"
            uses: devbotsxyz/xcode-notarize@v1 
            with:
              product-path: $PATH_TO_PKG
              appstore-connect-username: ${{ secrets.APPLE_ACCOUNT_USERNAME }}
              appstore-connect-password: ${{ secrets.APPLE_ACCOUNT_PASSWORD }}
              primary-bundle-id: 'BUNDLE_ID'

          - name: "Staple Release Build"
            uses: devbotsxyz/xcode-staple@v1
            with:
              product-path: $PATH_TO_PKG

  [...]

问题

我按照Github Action官方文档中的在macOS runner上安装苹果证书的步骤操作,部分功能按预期工作。我可以将证书添加到钥匙串并使用productsign命令对PKG文件进行签名。

但是,当我向Apple发送要求对PKG文件进行公证时,返回以下错误:

Error: Notarization status <invalid> - Package Invalid
Error: Notarization failed

我所尝试的

当分发时,PKG可以按预期工作(只需以管理员身份打开,因为它没有经过签名),因此问题似乎与包实现无关。

我尝试使用命令行执行标记操作,并跟随来自不同来源的链接:

但是,即使使用这些命令行(而不使用标记操作),我也无法将PKG文件进行标记。

问题

我的工作流程有什么问题,在尝试标记包之前,我是否漏掉了什么?

附注:我找不到任何在Github Actions macOS runner上执行此操作的参考...

2个回答

6
解决方案
在将devbotsxyz/xcode-notarize@v1字段设置为verbose:true后,我观察到苹果返回了一个JSON链接,解释了为什么该软件包无法进行公证的原因。
在这个JSON中,我被告知组成我的PKG文件的所有文件(由于上下文无法在Pyinstaller中使用--onefile)都是无效的,因为它们没有签名和时间戳。
经过一些研究,我找到了 Apple开发者论坛上的这篇帖子,并理解到PKG文件需要内外签名:首先,您需要为Pyinstaller生成的每个文件进行签名,然后再对PKG文件进行签名,将所有这些文件汇集到一起。
为了实现这一点,您不能使用productsign命令(因为它只适用于.pkg、.zip和.dmg文件),而是要使用codesign命令。
然而,codesign并不使用Developer Id Installer certificate,而是使用Developer Id Application certificate,所以我还需要将这个新的证书添加到工作流中。
请注意,由于我的PKG文件由数百个文件组成,我还需要一个bash脚本来使用codesign对每个文件进行签名
我的最终工作流如下所示:
jobs:
  [...]

  pkg:
    needs: [...]
    runs-on: macos-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Download macos bin file
        uses: actions/download-artifact@v2
        with:
          name: macos-bin-files
          path: dist/
      - name:
        run: | 
          ----- Create certificate files from secrets base64 -----
          echo ${{ secrets.DEVELOPER_ID_INSTALLER_CER }} | base64 --decode > certificate_installer.cer
          echo ${{ secrets.DEVELOPER_ID_INSTALLER_KEY }} | base64 --decode > certificate_installer.key
          echo ${{ secrets.DEVELOPER_ID_APPLICATION_CER }} | base64 --decode > certificate_application.cer
          echo ${{ secrets.DEVELOPER_ID_APPLICATION_KEY }} | base64 --decode > certificate_application.key

          ----- Create p12 file -----
          openssl pkcs12 -export -name zup -in certificate_installer.cer -inkey certificate_installer.key -passin pass:${{ secrets.KEY_PASSWORD }} -out certificate_installer.p12 -passout pass:${{ secrets.P12_PASSWORD }}
          openssl pkcs12 -export -name zup -in certificate_application.cer -inkey certificate_application.key -passin pass:${{ secrets.KEY_PASSWORD }} -out certificate_application.p12 -passout pass:${{ secrets.P12_PASSWORD }}

          ----- Configure Keychain -----
          KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
          security create-keychain -p "${{ secrets.KEYCHAIN_PASSWORD }}" $KEYCHAIN_PATH
          security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
          security unlock-keychain -p "${{ secrets.KEYCHAIN_PASSWORD }}" $KEYCHAIN_PATH

          ----- Import certificates on Keychain -----
          security import certificate_installer.p12 -P "${{ secrets.P12_PASSWORD }}" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
          security import certificate_application.p12 -P "${{ secrets.P12_PASSWORD }}" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
          security list-keychain -d user -s $KEYCHAIN_PATH

          ----- Codesign files with script -----
          use a script to sign each file from the artifact (ref: https://gist.github.com/GuillaumeFalourd/4efc73f1a6014b791c0ef223a023520a)

          ----- Generate PKG from codesigned files -----
          use a macos installer script (ref: https://github.com/KosalaHerath/macos-installer-builder/tree/master/macOS-x64)

          ----- Sign PKG file -----
          productsign --sign "${{ secrets.DEVELOPER_ID_INSTALLER_NAME }}" $INPUT_FILE_PATH $OUTPUT_FILE_PATH

          - name: Notarize Release Build PKG
            uses: lando/notarize-action@v2
            with:
              product-path: $PATH_TO_PKG
              appstore-connect-username: ${{ secrets.APPLE_ACCOUNT_USERNAME }}
              appstore-connect-password: ${{ secrets.APPLE_ACCOUNT_PASSWORD }}
    appstore-connect-team-id: FY8GAUX283 # if using notarytool

          - name: "Staple Release Build"
            uses: devbotsxyz/xcode-staple@v1
            with:
              product-path: $PATH_TO_PKG

  [...]

编辑:苹果已经更新了公证工具。之前在流程中使用的操作已经从市场上移除。
- name: "Notarize Release Build PKG"
  uses: devbotsxyz/xcode-notarize@v1 
  with:
   product-path: $PATH_TO_PKG
   appstore-connect-username: ${{ secrets.APPLE_ACCOUNT_USERNAME }}
   appstore-connect-password: ${{ secrets.APPLE_ACCOUNT_PASSWORD }}
   primary-bundle-id: 'BUNDLE_ID'

1
请注意,devbotsxyz/xcode-notarize 动作已被移除。现在的替代方案似乎是 https://github.com/lando/notarize-action。 - Anton Kochkov

1
我之前使用过notarize动作,但它已经不再维护,甚至无法使用了。不过,你可以直接在你的动作中使用xcrun工具:
  - name: Notarize Disk Image
    if: ${{ github.event_name == 'release' }}
    env:
      DMG_PATH: path/to/your/dmg
      AC_USERNAME: ${{ secrets.AC_USERNAME }}
      AC_PASSWORD: ${{ secrets.AC_PASSWORD }}
    run: xcrun notarytool submit ${DMG_PATH} --wait --apple-id ${AC_USERNAME} --password ${AC_PASSWORD} --team-id '<your team ID>'

  - name: Staple Release Build
    if: ${{ github.event_name == 'release' }}
    env:
      DMG_PATH: path/to/your/dmg
    run: xcrun stapler staple ${DMG_PATH}

  - name: Upload Release Assets
    if: ${{ github.event_name == 'release' }}
    run: gh release upload ${{ github.ref }} ${DMG_PATH}
    env:
      DMG_PATH: path/to/your/dmg
      GH_TOKEN: ${{ secrets.GH_TOKEN }}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接