签署和公证 Python MacOS UI 应用程序

使用 Python 编写的 MacOS 应用程序经过 Catalina 公证的指南。

为什么要用 Python 编写 MacOS 应用程序?

Python 拥有极其丰富的库、工具和框架生态系统。它是一种干净、现代的语言,允许快速原型设计和快速开发周期。UI 不是我的应用程序的中心和焦点,所以用 Python 做它对我来说很有意义:我想我会先编写核心功能,然后再添加 UI。

打包应用程序

MacOS Catalina(2019 年发布)仍然没有默认安装 Python 3,只有 Python 2。因此,我需要一种方法将整个应用程序打包成一个应用程序包,而不是让它依赖于用户的 Python 安装。有几个工具可以帮助解决这个问题:py2app、 公文包pyinstaller。我决定使用 PyInstaller,它成熟、灵活,并且提供比其他选项更多的自定义。

第 1 步:PyInstaller 规范文件

PyInstaller 可以单独由命令行选项驱动,但这仅适用于最简单的情况,并且打包任何非平凡的应用程序都不是其中之一。我建议使用命令行参数运行它,这会使用默认值创建规范文件,然后修改规范文件以更好地满足您的需求。例如,将捆绑版本设置为与应用程序版本相同的值,并添加一些自定义 plist 值:

from my_application import __version__ as package_version
...

...
# The final bundling step in the spec file:
# reference: https://pyinstaller.readthedocs.io/en/stable/spec-files.html#spec-file-options-for-a-mac-os-x-bundle
app = BUNDLE(coll,
    name='My Application.app',
    icon='my_application/resources/my_application.icns',
    bundle_identifier='com.example.my_application',
    info_plist={
      'CFBundleName': 'My Application',
      'CFBundleDisplayName': 'My Application',
      'CFBundleVersion': package_version,
      'CFBundleShortVersionString': package_version,
      'NSRequiresAquaSystemAppearance': 'No',
      'NSHighResolutionCapable': 'True',
    },
)

第 2 步:构建应用程序

这很简单

  pyinstaller --noconfirm my_application.spec

My Application.app将被创建,您可以(并且应该)测试以确保它确实有效。一些 Python 包需要在 PyInstaller 规范文件中进行调整:包括包中的额外数据文件等。

第 3 步:签署应用程序

为了能够对其进行公证,您必须使用强化运行时。Hardened Runtime 不会影响大多数应用程序的运行,但它不允许某些功能。特别是对于 Python 应用程序,我们需要允许未签名的可执行内存。如果您的应用程序依赖于 Hardened Runtime 限制的任何其他功能,请添加一项权利以禁用该个人保护。

添加entitlements.plist到项目的根目录:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <!--
    These are required for binaries built by PyInstaller.
    For more info, see:
      https://developer.apple.com/documentation/security/hardened_runtime
      https://github.com/pyinstaller/pyinstaller/issues/4629
  -->
  <dict>
    <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
    <true/>
  </dict>
</plist>

现在我们准备签署:

codesign -s Developer -v --deep --timestamp --entitlements entitlements.plist -o runtime "dist/My Application.app"

请注意,为了能够对应用程序进行公证,您需要使用您的 Apple Developer ID 证书对其进行签名。如果需要,调整上面的“开发人员”以匹配您的证书名称。

Apple 建议不要“深度签名”,但在这种情况下,它实际上是必需的,因为所有捆绑的 Python 库都需要签名,而不仅仅是主二进制文件。

通过添加--timestamp参数,我们包含一个带有代码签名的安全时间戳。这是公证的要求。

通过添加权利文件并传递-o runtime参数,我们启用了强化运行时,这也是公证的要求。

第 3 步:对应用程序进行公证

为了能够对应用程序进行公证,您需要满足一些额外的要求:

  • 应用程序中的所有二进制文件都必须链接到 macOS 10.9 或更高版本的 SDK。如果您只是使用最新的 Xcode 重新构建所有内容,则可以满足此要求。但是,如果您使用预先构建的二进制扩展打包一些 Python 依赖项,则它可能是针对较旧的 SDK 构建的。在这种情况下,您需要从源代码构建这个特定的包。
  • 不包括明确禁止的权利。在撰写本文时,这只是一项 com.apple.security.get-task-allow权利。

将 Apple 凭据存储在钥匙串中

为了对应用程序进行公证,altool必须能够代表您访问 Apple API。要确保此访问的安全,请将您的 Apple 帐户凭据存储在钥匙串中:

xcrun altool --store-password-in-keychain-item "AC_PASSWORD" -u "your-username" -p "your-password"

公证吧!

由于altool需要 Zip 存档而不是裸.app目录,因此请先创建一个 Zip 文件,然后对其进行公证: .

ditto -c -k --keepParent "dist/My Application.app" dist/MyApplication.zip
xcrun altool --notarize-app -t osx -f dist/MyApplication.zip \
    --primary-bundle-id your.bundle.id -u your-username --password "@keychain:AC_PASSWORD"

现在您需要等待公证结果。一旦完成,您将收到来自 Apple 的电子邮件,说明成功或失败(并在这种情况下链接到错误日志)。

第 4 步:装订应用程序

在上面的公证步骤中,Apple 已经创建了一张“票”,它基本上是一个数据库记录,它与您的应用程序的签名相匹配并表示它已经过公证。您的二进制文件没有以任何方式被修改。当 MacOS 运行此应用程序时,它会联系 Apple 服务器并索要票证。如果存在这样的票证,则该应用程序被视为“经过公证”这只会发生一次,然后 MacOS 将缓存结果。

如果我们想加速这个初始应用程序的执行,或者如果我们希望能够在离线时运行它,我们需要“将这张票装订到应用程序”,它会下载票并将其附加到您的二进制文件中。这很简单:

xcrun stapler staple "dist/MyApplication.app"

此步骤是可选的,但必须在您收到 Apple 发送的说明公证成功的电子邮件后运行。

第 5 步:验证

现在是验证一切正常的好时机:

  spctl --assess --type execute -vvv "dist/My Application.app"

此命令直接使用 Gatekeeper 来评估应用程序是否正确签名和公证。它应该报告:

dist/My Application.app: accepted
source=Notarized Developer ID
origin=Developer ID Application: YourName (XXX)

结论

虽然上面概述的过程今天有效,但它肯定很麻烦并且有一些缺点:

  • 开发和构建过程比使用 Xcode 的普通 MacOS 开发过程复杂得多。让新开发人员加入会很棘手。
  • 很难控制被拉入应用程序的库。如果某些依赖项是使用 Homebrew 构建的,则该应用程序可能无法在比构建机器更旧的 MacOS 版本上运行。

在我看来,用 Python 编写 MacOS 应用程序对于原型设计或快速构建简单的内部工具是可接受的途径,甚至对应用程序进行公证也是完全可行的。

 

 

原文链接https://haim.dev/posts/2020-08-08-python-macos-app/

0回复签署和公证 Python MacOS UI 应用程序"

留言

邮箱地址不会被公开。 必填项已用*标注

2017-2021仙人掌教育版权所有
京ICP备18004382号-1