macOS:在脚本中公证?

时间:2019-07-04 15:13:10

标签: macos notarize

由于Xcode的代码签名和归档非常耗时,枯燥且有问题,因此我一直使用命令行工具xcodebuild,{{1} }等通过我自己的脚本。公证看起来将是一个巨大的痛苦。可以在我的脚本中添加公证吗?

3 个答案:

答案 0 :(得分:4)

是的。不幸的是,official answer留下了一些松散的结局,例如这个important tidbit from Quinn "the Eskimo"。这是操作方法:

一次性设置

获取应用专用密码

为经过公证的应用确定“应用”的名称。我使用产品运输脚本的名称SSYShipProduct.pl,因为这是将使用此密码的“应用程序”。我们会将您撰写的任何名称称为 your-notarizing-name

浏览到https://appleid.apple.com/account/manage,滚动到安全> 应用专用密码,然后为 app 命名为您的公证名称。复制它提供给您的密码。我们将其称为 app-specific-password

将特定于应用程序的密码添加到您的macOS钥匙串中

运行以下命令将您刚创建的密码添加到钥匙串:

security add-generic-password -a "your-apple-ID-email" -w "app-specific-password" -s "your-notarizing-name"

-s参数是此项目将在您的钥匙串中使用的名称。我认为您实际上可以使用其他名称,但是在我看来,也可以在此处使用your-notarizing-name

您可以通过在 Keychain Access 应用程序中进行搜索来验证其是否有效。但是,请注意,直到退出并重新启动后,钥匙串访问中才会列出新项目。

也许,获取相关的 itc-provider

如果您的Apple ID与一个以上的Apple Developer Connection团队相关联(例如,如果您从事合同工作),则需要该应用程序应经过公证的团队的 itc_provider

要找到您团队的 itc_provider ,请执行以下命令:

/Applications/Xcode.app/Contents/Applications/Application\ Loader.app/Contents/itms/bin/iTMSTransporter -m provider -u "your-apple-ID-email" -p "app-specific-password"

滚动到此命令输出的输出的末尾,并查看 Provider listing 表。复制所需团队的简称。我们将其称为“ developer-team-itc-provider”。

对于每个货件(可编写脚本!)

如果您使用/usr/bin/codesign命令行工具对应用程序的组件进行签名,则每次对codesign的调用都必须具有以下新的parameter参数,该参数告诉codesign使用所谓的硬化运行时进行签名

 `--options runtime`

相反,如果您的应用程序已使用Xcode登录,则必须在所有可执行组件目标中将Xcode 10或更高版本中可用的构建设置 Hardened运行时设置为

除此之外,与公证前的日子一样,您的脚本应在Release配置中创建应用的构建并对其进行代码签名。

上传到Apple Notary服务

然后,您的脚本应将您的应用程序存档为.zip或.dmg。请注意,这是一个临时文件,将仅上传到Apple Notary服务,而不附带。

然后,您的脚本应组成一个主捆绑包ID值,该值将是您应用的捆绑包标识符,后面附加.zip.dmg。例如:您的出价值 = com.mycompany.YourApp.zip

接下来,您的脚本将使用altool,它是Apple在 Application Loader Tool 中的名称。

然后,您的脚本应运行此命令以对.zip或.dmg进行公证:

编辑2019-07-09。请阅读@khuttun关于添加--output-format参数以获得结构化输出的以下第一条评论。

/usr/bin/xcrun altool --notarize-app --primary-bundle-id "your-pbid-value" --username "your-apple-id-email" --password "@keychain:your-notarizing-name" -itc_provider "developer-team-itc-provider" --file /path/to/YourApp.zip/or/YourApp.dmg

(请注意,在上述命令中,奇怪的是,所有参数名称都以两个破折号开头,除了-itc_provider仅以一个破折号开头。此外,如果您使用的脚本语言是内插@字符串中的字符,对其进行编码以防止@keychain的插值。

大约一分钟后,xcrun将退出并打印到stderr结果,其中包括 Request UUID 。示例:

No errors uploading '/path/to/YourApp.zip'.
RequestUUID = 605e0ae5-9106-4dd6-8e85-b3a9b3f12c0b

在这一点上,我建议您的脚本删除上载的.zip.dmg文件。原因:该文件是从尚未将您的公证证书装订在其上的产品中归档的。在脚本的最后,您将从具有票证的修改后的应用程序中创建新的.zip.dmg。立即删除该文件可防止您误寄未装订的应用程序。

然后您的脚本需要以上输出中的RequestUUID值。如果此结果为文档格式,JSON或其他格式,那将是很好的选择,但是不幸的是,所以它不是,所以我们所能做的就是尝试使用一种可靠的方式解析RequestUUID,我们希望该方法可以面向未来。我们最好的判断。这是我在Perl中执行的操作,检查stdout以防stderr空手返回:

$stderr =~ m/equestUUID[\s=]+([^\s]+)/;
my $requestUuid = $1;
if (length($requestUuid) < 10) {
    $stdout =~ m/equestUUID[\s=]+([^\s]+)/;
    $requestUuid = $1;
}

循环等待苹果的回应

您的脚本随后可以通过循环运行此命令并进行一些睡眠来开始困扰苹果的服务器以获得最终结果:

/usr/bin/xcrun altool --notarization-info <Request UUID> --username "your-apple-id-email" --password "@keychain:your-notarizing-name"

如果您的脚本立即运行此命令,它将在stderr中得到一个类似于以下内容的结果(省略时间戳,删除空格)

No errors getting notarization info.
RequestUUID: 885aeaa1-743f-4462-97d9-f79a0f679bc4
Date: 2019-07-01 07:14:36 +0000
Status: in progress
LogFileURL: (null)

通常在几分钟后(Apple说“应该少于一个小时”,但是我在2019年7月4日下午经历了1:35和3:30 hours:mins的时间),您的脚本将会同样在stderr中,结果是这样的:

No errors getting notarization info.
RequestUUID: 885aeaa1-743f-4462-97d9-f79a0f679bc4
Date: 2019-07-01 07:14:36 +0000
Status: in progress
LogFileURL: (null)
Status Code: 0
Status Message: Package Approved

再过几秒钟,再次在stderr中,如下所示:

No errors getting notarization info.
RequestUUID: 885aeaa1-743f-4462-97d9-f79a0f679bc4
Date: 2019-07-01 07:14:36 +0000
Status: success
LogFileURL: https://osxapps-ssl.itunes.apple.com/. . .
Status Code: 0
Status Message: Package Approved

因此,在每次循环迭代中,您的脚本都应解析出Status的值,并在其变为in progress以外的其他内容时退出循环,但是再次感谢Apple提供的一些文档

公证完成后,无论成功与否,您还将收到Apple的电子邮件。

检查Apple的日志文件

接下来,您的脚本应解析出LogFileURL:之后的值,因为即使公证成功,Apple创建的日志文件也可能包含警告。要获取日志文件,您的脚本当然应该

curl <LogFileURL-Value>

日志文件显然是JSON。警告或错误以数组的形式显示,它是键issues的值。因此,您的脚本应使用JSON解析器解析curl的输出,并且如果键issues的值为JSON空或空数组,请继续发货。

将票证装到您的应用程序中

这一步很容易...

xcrun stapler staple /path/to/YourApp.app

运行此命令会将一个新文件添加到您的应用包中:YourApp.app/Contents/CodeResources。这显然是您的公证证件。请注意,该文件是文件YourApp.app/Contents/_CodeSignature/CodeResources的补充,文件spctl -a -v /path/to/YourApp.app 仍然存在,并且包含代码签名,与公证前的日子相同。

验证订票装订

但是有一种更好的方法来验证您的应用程序现在是否具有良好的票证。您的脚本现在应该运行(或重新运行)Gatekeeper检查:

/path/to/YourApp.app: accepted
source=Notarized Developer ID

在stderr中的结果应该是

{{1}}

除了插入 Notarized 之外,与预公证的结果相同。如果未检测到上述单词,则精明的脚本将解析该stderr并中止发货。

邮寄和运送

现在已经添加了票证,您的脚本可以再次对.app进行zip或dmg处理,但这一次,将其发送。

答案 1 :(得分:2)

以下是用于自动构建的可重用和免费许可的公证和订书钉脚本:

https://github.com/rednoah/notarize-app/blob/master/notarize-app

它将运行并等待,直到一切完成后才退出:

  1. 运行altool --notarize-app
  2. 定期运行altool --notarization-info直到公证完成
  3. 运行stapler staple

答案 2 :(得分:0)

这是我为RawTherapee编写的示例自动公证人。首先,我们对应用程序进行公证:

https://github.com/Beep6581/RawTherapee/blob/6fa533c40b34dec527f1176d47cc6c683422a73f/tools/osx/macosx_bundle.sh#L225-L250

然后我们对dmg进行公证:

https://github.com/Beep6581/RawTherapee/blob/6fa533c40b34dec527f1176d47cc6c683422a73f/tools/osx/macosx_bundle.sh#L283-L307

公证凭证通过cmake命令指令

传递
-DNOTARY="--username user@mail.com --password abcd-efgh-ijkl-mnop"