由于代码签名和Xcode的存档费时,枯燥和有问题的,我一直codesigned,归档和运签署我的开发者ID的MacOS应用程序中使用的命令行工具xcodebuild
,codesign
等等。通过我自己的脚本。公证看起来将是一个巨大的痛苦。是否可以在脚本中添加公证?
Jer*_*ock 15
是。不幸的是,官方答复留下了一些松散的结局,例如奎因(Quinn)的《爱斯基摩人》(Eskimo)的重要消息。这是操作方法:
确定公证应用的“应用”的名称。我使用产品运输脚本的名称,SSYShipProduct.pl
因为这是将使用此密码的“应用程序”。我们将把您撰写的任何名称都称为your-notarizing-name。
浏览到https://appleid.apple.com/account/manage,滚动到“ 安全性” >“ 应用程序专用密码”,然后为名为your-notarizing-name的应用程序生成应用程序专用密码。复制它提供给您的密码。我们将其称为app-specific-password。
运行以下命令以将刚创建的密码添加到钥匙串中:
security add-generic-password -a "your-apple-ID-email" -w "app-specific-password" -s "your-notarizing-name"
该-s
参数是,这个项目将在您的钥匙串的名称。我认为您实际上可以使用其他名称,但是在我看来,your-notarizing-name
在此处使用也很有意义。
您可以通过在“ 钥匙串访问”应用程序中搜索来验证它是否有效。但是,请注意,直到退出并重新启动后,新项目才会在“ 钥匙串访问”中列出。
如果您的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"
滚动到此命令输出的输出的末尾,然后查看提供者列表。复制所需团队的简称。我们将其称为“ developer-team-itc-provider”。
如果使用/usr/bin/codesign
命令行工具对应用程序的组件进行签名,则每次对codesign的调用都必须具有以下新的parameter参数,该参数告诉codesign使用所谓的强化运行时进行签名:
`--options runtime`
Run Code Online (Sandbox Code Playgroud)
相反,如果您的应用程序已用Xcode签名,则必须在所有可执行组件目标中将Xcode 10或更高版本中可用的“ Build Setting Hardened”运行时设置为“ 是”。
除此之外,与公证前的日子一样,您的脚本应在Release配置中创建应用的构建并对其进行代码签名。
然后,您的脚本应将您的应用存档到.zip或.dmg。请注意,这是一个临时文件,将仅上传到Apple Notary服务,而不附带。
然后,您的脚本应组成一个主要的捆绑包ID值,该值将是您应用的捆绑包标识符,.zip
或.dmg
附加在其后。示例:your-pbid-value = com.mycompany.YourApp.zip
。
接下来,您的脚本将使用altool
,这是Apple的Application Loader Tool的名称。
然后,您的脚本应运行以下命令以对.zip或.dmg进行公证:
/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 --output-format "xml"
(请注意,在上面的命令中,奇怪的是,所有参数名称都以两个破折号开头,但-itc_provider
仅以一个破折号开头。此外,如果您使用的脚本语言是@
在字符串中插入字符,请对其进行编码以防止插入@keychain
)。
xcrun
大约一分钟后,将退出并打印以输出一些XML,如果您的提交被接受(注意:尚未批准),则该XML 将类似于以下示例:
<?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">
<dict>
<key>notarization-upload</key>
<dict>
<key>RequestUUID</key>
<string>2ab59b26-19ec-4a30-84cf-6d2cb8d3c97e</string>
</dict>
<key>os-version</key>
<string>10.15.0</string>
<key>success-message</key>
<string>No errors uploading 'path/to/YourApp.zip'.</string>
<key>tool-path</key>
<string>/Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/Frameworks/ITunesSoftwareService.framework</string>
<key>tool-version</key>
<string>1.1.1138</string>
</dict>
</plist>
Run Code Online (Sandbox Code Playgroud)
您真正需要的就是这些RequestUUID
价值。但是,由于我经常发布四个应用程序,并且由于我的发布脚本失败而又没有提供有用的错误信息,这毁了我的一天,并且因为(请参阅下文)您将要进行另一个调用,该调用也返回了有趣的XML,因此我花了一些时间在我的脚本中添加了一个子例程,该子例程带有两个参数,即XML和一个密钥路径,并在给定的密钥路径下返回XML的值。在上述情况下,我调用此子例程获取RequestUUID
,然后再次获取success-message
。
(我的脚本在Perl中。尽管CPAN中有一个名为XML :: Simple的模块,可以在一两行中进行此解析,但维护人员将其标记为不用于新设计。因此,避免了需要要使用真正的 XML解析器安装和纠缠,我选择使用PlistBuddy
@khuttun的注释中建议的方法,这有点痛苦,因为不幸的是,altool
它没有选择将其输出写入文件,并且PlistBuddy
没有记录接受stdin。因此,我的子例程将stdout从写入altool
临时文件,然后将该临时文件的路径传递给PlistBuddy。有点令人讨厌,但它可以工作。)
此时,我建议您的脚本删除其上载的.zip
或.dmg
文件。原因:该文件是从尚未装订公证证件的产品中存档的。在脚本末尾,您将创建一个新的.zip
或.dmg
从带有票证的修改后的应用程序。立即删除文件可防止您错误地运送未装订的应用程序。
然后,通过循环运行以下命令并进行一些睡眠,您的脚本可以开始为您的最终结果困扰Apple的服务器:
`/ usr / bin / xcrun altool --notarization-info --username“ your-apple-id-email” --password“ @keychain:your-notarizing-name”-输出格式“ xml”
如果您的脚本立即运行此命令,它将在stdout中返回一些xml,看起来像下面的示例:
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>notarization-info</key>
<dict>
<key>Date</key>
<date>2019-08-07T01:17:37Z</date>
<key>RequestUUID</key>
<string>4ba71353-9d99-4b52-b579-37f384717130</string>
<key>Status</key>
<string>in progress</string>
</dict>
<key>os-version</key>
<string>10.15.0</string>
<key>success-message</key>
<string>No errors getting notarization info.</string>
<key>tool-path</key>
<string>/Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/Frameworks/ITunesSoftwareService.framework</string>
<key>tool-version</key>
<string>1.1.1138</string>
</dict>
</plist>
Run Code Online (Sandbox Code Playgroud)
其中的重要关键路径是notarization-info:Status
,其值in progress
表示Apple仍在处理您的提交。通常在几分钟后(Apple说“应该少于一个小时”,但是我在2019年7月4日美国假日下午经历了长达三个半小时的时间),altool
将使用不同的xml返回脚本在标准输出中,如下所示:
<?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">
<dict>
<key>notarization-info</key>
<dict>
<key>Date</key>
<date>2019-08-06T23:28:25Z</date>
<key>LogFileURL</key>
<string>https://osxapps-ssl.itunes.apple.com/itunes-assets/Enigma113/v4/f6/09/be/f609bee3-b031-323a-0987-d1f620a78758/developer_log.json?accessKey=1565410613_1722173034418364591_TvycjBAzd6FRTYGKZEFU6EwDfsws8Wa1MV%2FYnTiJ1zyOZamc%2FoeO5RMeIzZN669ZQJgO2Q4W48ipKNFO%2BQGuq%2FITXN8MQAetbNe90w9ogzqXbrzTHg%2FgYK89yvEFmiiRxhaVlZqLI93NBpY0hwBqXv2bvvlg%2FRCc%2BVaCNRJ%2BrnE%3D</string>
<key>RequestUUID</key>
<string>07fc3745-b0ff-4d1a-9b15-37f384717130</string>
<key>Status</key>
<string>success</string>
<key>Status Code</key>
<integer>0</integer>
<key>Status Message</key>
<string>Package Approved</string>
</dict>
<key>os-version</key>
<string>10.15.0</string>
<key>success-message</key>
<string>No errors getting notarization info.</string>
<key>tool-path</key>
<string>/Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/Frameworks/ITunesSoftwareService.framework</string>
<key>tool-version</key>
<string>1.1.1138</string>
</dict>
</plist>
Run Code Online (Sandbox Code Playgroud)
经过一些反向工程之后,您会看到,在每次循环迭代中,只要的值Status
不是in progress
或LogFileURL
定义了when,则脚本应该解析XML并退出循环。或者,如果您更喜欢电子邮件触发器,则脚本可以查找主题行来自Apple的电子邮件。现在,您可以分发Mac软件。。
更新2019-11-02
在最后几次发货后(今天又是今天)遇到了这一步骤的麻烦之后,我现在确认了Apple的Notary Service中的错误。错误是altool --notarization-info
命令将在1-5个小时内失败,返回非零退出代码,并在stdout中显示错误代码1519“找不到RequestUUID”,如以下示例stdout中所示:
<?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">
<dict>
<key>os-version</key>
<string>10.15.1</string>
<key>product-errors</key>
<array>
<dict>
<key>code</key>
<integer>1519</integer>
<key>message</key>
<string>Could not find the RequestUUID.</string>
<key>userInfo</key>
<dict>
<key>NSLocalizedDescription</key>
<string>Could not find the RequestUUID.</string>
<key>NSLocalizedFailureReason</key>
<string>Apple Services operation failed.</string>
<key>NSLocalizedRecoverySuggestion</key>
<string>Could not find the RequestUUID.</string>
</dict>
</dict>
</array>
<key>tool-path</key>
<string>/Applications/Xcode.app/Contents/SharedFrameworks/ContentDeliveryServices.framework/Versions/A/Frameworks/AppStoreService.framework</string>
<key>tool-version</key>
<string>4.00.1181</string>
</dict>
</plist>
Run Code Online (Sandbox Code Playgroud)
这是一个错误,因为,当然,我的剧本没有提交它刚刚从苹果公证服务接收到的请求UUID,苹果应该能够找到它,而且,当我不停手动发送命令,约2小时后,突然,该命令返回Success
并继续返回Success
后续命令,然后我收到了来自Apple 的成功电子邮件。今天,这种延迟发生了,有7个不同的良好Request UUID,最长为5小时。可能此时,Apple Notary Service创建与向您发送请求UUID之间存在1-5小时的延迟,并且该延迟出现在数据库中,Apple Notary Service用于响应notarization-info
请求,因此您会收到此错误消息。很伤心
因为我有当苹果转让人修正错误,我已经修改了这个阶段,我的脚本来解析来自苹果的回应并无控制,死亡仅当命令返回非零退出状态,并在code
第一(指数= 0)product-errors
数组项不是1519。如果您按原样使用PlistBuddy解析XML,则其关键路径应为代码product-errors:0:code
。每当收到错误1519时,脚本中的循环都会打印出来,因此我可以看到发生了什么,当然,我修改了它的while
条件,以使错误代码为1519时不退出。
修改完脚本后,我发布了几个应用程序。Apple Notary Service很好地对待了第一个:No Error 1519,大约两分钟后成功。但是,下一个需要我脚本的新功能。在时间09:54(HH:mm),我的脚本收到了Apple的Request UUID。20秒后,它发送了第一个altool --notarization-info
查询。响应是错误的错误1519。后续查询也返回错误的错误1519,持续了将近3个小时,直到12:44。然后,在12:45,它突然收到了in progress
响应。经过5次in progress
回复后,终于在12:47 成功。
离开本主题之前的另一件事:该请求成功执行一个小时,没有出现错误1519,一个小时前的先前请求突然开始返回in progress
,然后几分钟后返回Success。结论:绕开到错误1519混乱中的请求UUID不会与以后的请求UUID一起排队在FIFO中,后者可能会避免错误1519绕道。因此,更好的解决方法可能是在收到另一个错误1519响应后放弃请求UUID,然后通过将应用程序重新上载到Apple Notary Service重新开始,并获取另一个您希望能更好地工作的请求UUID。当然,由于您放弃的所有请求UUID最终都会成功,因此在接下来的几个小时内您会收到许多电子邮件。
无论如何,现在,继续进行脚本的下一步…
您的脚本应该解析出的值,LogFileURL
以便可以检查日志,因为即使公证成功,Apple创建的日志文件也可能包含警告。要获取日志文件,您的脚本当然应该
curl <LogFileURL-Value>
Run Code Online (Sandbox Code Playgroud)
日志文件显然是JSON。警告或错误以数组形式显示,它是key的值issues
。因此,您的脚本应curl
使用JSON解析器解析该输出,并且如果key的issues
值为JSON null或空数组,请继续发货。
这一步很容易...
xcrun stapler staple /path/to/YourApp.app
Run Code Online (Sandbox Code Playgroud)
运行此命令会将一个新文件添加到您应用的软件包中YourApp.app/Contents/CodeResources
。这显然是您的公证单。请注意,此文件是对YourApp.app/Contents/_CodeSignature/CodeResources
仍存在的文件的补充,并且包含代码签名,与公证前的日子相同。
但是,有一种更好的方法来验证您的应用程序现在是否有票证。您的脚本现在应该运行(或重新运行)Gatekeeper检查:
spctl -a -v /path/to/YourApp.app
Run Code Online (Sandbox Code Playgroud)
在stderr中,结果应该是,
/path/to/YourApp.app: accepted
source=Notarized Developer ID
Run Code Online (Sandbox Code Playgroud)
除了插入Notarized以外,与预公证的结果相同。如果未检测到上述单词,则精明的脚本将解析该stderr并中止发货。
现在已经添加了票证,您的脚本可以再次对.app进行zip或dmg处理,但这一次,将其发送出去。
这是一个可重复使用且免费许可的公证和订书脚本,用于自动构建:
https://github.com/rednoah/notarize-app/blob/master/notarize-app
它会运行并等待,只有在一切完成后才退出:
altool --notarize-app
altool --notarization-info
直至公证完成stapler staple
归档时间: |
|
查看次数: |
1163 次 |
最近记录: |