如何公证在 XCode 之外创建的 MacOS 命令行工具?

How to notarize an MacOS command line tool created outside of XCode?

MacOS 现在要求所有应用程序都经过强化、签名和公证。如何使用 PyInstaller 等工具对在 XCode 之外创建的应用程序进行签名和公证?

我已经解决了 .app 在 XTools 之外创建的文件的签名和公证。有一个非常有用的线程 here 展示了如何添加一个 entitlements.plist 来实现 PyInstaller .app 文件的强化。我相信这也适用于命令行实用程序,但可能会遗漏一些东西。使用 altool 提交包含 .app.dmg 进行公证将通过测试并由 Apple 进行公证。

使用相同的过程提交单个命令行实用程序也将通过公证,但不会显示为其他计算机上的 GateKeeper 功能签名或公证。我认为这与有效的 Info.plist 文件未包含在 PyInstaller 二进制文件中有关,如 this blog post about building and delivering command line tools for Catalina.

中所述

使用codesign -dvv检查签名文件的签名表明Info.plist“未绑定”。

$ codesign -dvv ./dist/helloworld
Executable=/Users/aaronciuffo/Documents/src/toy/codesign/dist/helloworld
Identifier=helloworld
Format=Mach-O thin (x86_64)
CodeDirectory v=20500 size=72086 flags=0x10000(runtime) hashes=2244+5 location=embedded
Signature size=9054
Authority=Developer ID Application: Aaron Ciuffo (4H9P6Q65AM)
Authority=Developer ID Certification Authority
Authority=Apple Root CA
Timestamp=Nov 2, 2020 at 9:03:30 PM
Info.plist=not bound
TeamIdentifier=4H9P6Q65AM
Runtime Version=10.11.0
Sealed Resources=none
Internal requirements count=1 size=172

一个 suggested solution is using the Go gon package 但据我所知 gon 不包括添加所需的 Info.plist

是否有工作流或应用程序可以对此提供帮助?如何在 XCode 之外创建 CL 应用程序并成功签名?

如何手动签署和公证命令行工具

Apple 要求所有分发的二进制文件都使用付费的 Apple 开发者帐户进行签名和公证。对于使用 PyInstaller 等工具创建的二进制文件或使用 gcc 编译的二进制文件,可以使用命令行工具来完成。

此过程的自动化Python脚本

下面链接的脚本允许您使用项目特定 .ini 文件自动执行此过程。

codesign.py

设置

如果您已经拥有在 XCode 中配置了 Developer ID ApplicationDeveloper ID Installer 证书的开发者帐户,请跳过此步骤

  • 创建 Apple 开发者帐户
  • 从 Apple App Store 下载并安装 X-Code
  • 打开 运行 X-Code 应用程序并安装它需要的任何附加功能
  • 打开首选项窗格 (cmd+,) 并选择 帐户
    • 点击左下角的+
    • 选择Apple ID
    • 输入您的 Apple ID 和密码
    • 可以从 https://developer.apple.com
    • 下载并安装之前创建的密钥
  • Select您要使用的开发者帐号
  • 选择管理证书...
  • 点击左下角的+选择开发者ID申请
  • 点击左下角的+,选择Developer ID Installer

创建一个 App-Specific 密码供 altool 使用

Instructions from Apple

  • 打开KeyChain Access
  • 创建“新密码项”
    • 钥匙串项目名称:Developer-altool
    • 账户名:您的开发者账户邮箱
    • 密码:您刚刚创建的application-specific密码

使用 Pyinstaller 或其他工具创建可执行二进制文件

注意! 构建功能二进制文件可能需要额外的参数,例如 --add-data

  • 创建一个二进制文件
    • pyinstaller --onefile myapp.py

签署可执行文件

  • 将 entitements.plist 添加到目录(见下文)
  • 列出可用密钥并找到 Developer ID Application 证书:
    • security find-identity -p basic -v
    1) ABC123 "Apple Development: aaronciuffonl@gmail.com ()"
    2) XYZ234 "Developer ID Installer: Aaron Ciuffo ()"
    3) QRS333 "Developer ID Application: Aaron Ciuffo ()"
    4) LMN343 "Developer ID Application: Aaron Ciuffo ()"
    5) ZPQ234 "Apple Development: aaron.ciuffo@gmail.com ()"
    6) ASD234 "Developer ID Application: Aaron Ciuffo ()"
    7) 01010A "Developer ID Application: Aaron Ciuffo ()"
       7 valid identities found
    
  • codesign --deep --force --options=runtime --entitlements ./entitlements.plist --sign "HASH_OF_DEVELOPER_ID APPLICATION" --timestamp ./dist/foo.app

打包为 pkg 用于安装

  • 创建一个临时目录来构建包:
    • mkdir /tmp/myapp
  • 使用同上构建 pkg 安装程序结构
    • ditto /path/to/myapp /tmp/myapp/path/to/install/location
      • 将应用程序“WhizBang”安装到 /Applications/ 目标上使用:ditto ~/src/whiz_bang/dist/whizBang /tmp/whiz_bang/Applications/
    • 对应打包的所有文件重复此操作
  • 构建包
  • productbuild --identifier "com.your.pkgname.pkg" --sign "HASH_OF_INSTALLER_ID" --timestamp --root /tmp/myapp / myapp.pkg
  • NB! --root 选项的格式如下: --root <ditto path> <relative path on target system to install from> <signed .pkg file>

公证

  • xcrun altool --notarize-app --primary-bundle-id "com.foobar.fooapp" --username="developer@foo.com" --password "@keychain:Developer-altool" --file ./myapp.pkg
  • 检查电子邮件是否已成功公证
    • 或者使用以下方式检查状态:
      • xcrun altool --notarization-history 0 -u "developer@***" -p "@keychain:Developer-altool"
  • 如果公证失败,请使用以下方法查看详细日志:
  xcrun altool --notarization-info "Your-Request-UUID" \
             --username "username@example.com" \                                    
             --password "@keychain:Developer-altool"   

对 pkg 进行装订公证

  • 将公证添加到 pkg
    • xcrun stapler staple ghostscript64.pkg

有用的资源

伤害分配

使用 Aaron Ciuffo 的 post 将 PKG 命令与此交换

如果您想在 DMG 中分发二进制文件,除了对二进制文件调用代码签名之外,您还必须正确创建 DMG。

首先创建您的文件夹并清除所有垃圾,否则上传将失败。

mkdir DistributionFolder
xattr -cr ./DistributionFolder

然后将二进制文件移至该文件夹并创建一个适当大小的 DMG

hdiutil create -fs HFS+ -volname MyApp -srcfolder ./DistributionFolder ./Distribution.dmg

弹出驱动器。签署 DMG 并上传。一旦经过公证,您就可以像亚伦的回答一样装订。