公证系列:
- WWDC22: juejin.cn/post/711162…
1: Notarization的更新
1.1: 公证传统的workflow
在WWDC19, 苹果在MacOS 10.14之后引入了公证(Notarization)这一机制来提升安全性. 主要分以下几步
1: 用xcrun altool --notarize-appupload zip/dmg/pkg到 server,
2: 然后等待requestUUID的返回,
3: 再根据requestUUID来不断轮询查询结果, 如果成功的话绑定返回的ticket.
然而将这个过程植入pipeline中是一个相当麻烦的过程, 如果Upload的bundle过大的时候, upload 和查询结果都需要花很长的时间 而且一般的pipeline都需要同时提交很多bundle. 单个app公证代码如下:
公证的过程图:
1.2: 新的公证workflow
在WWDC21中, 苹果为了降低公证的复杂度引入了notarytool用来替换之前的xcrun,可以通过一个命令行直接查询到公证结果, 使公证更快更容易.
除了开发者使用notarytool这一个改动, 苹果也精简了notarization service. 苹果构建了一个新的专用Notarization的server, 该server为Notary提供更大的可靠性, 并且会使upload bundle的速度提升四倍.
2: notarytool的使用
2.1 将AC_USERNAME和AC_PASSWORD存在keychain里
为了避免在命令行中明文使用AC_USERNAME和AC_PASSWORD, 苹果在WWDC21里提供了一个命令行可以将AC_USERNAME和AC_PASSWORD存在本地的keychain里:
// 在keychain里新增一个名为NotarizationItemName(名字随便起)的Item
xcrun notarytool store-credentials "NotarizationItemName" --apple-id "$Your_AC_USERNAME" --team-id "$YourTeamId" --password "$Your_ACPassword"
This process stores your credentials securely in the Keychain. You reference these credentials later using a profile name.
Validating your credentials...
Success. Credentials validated.
Credentials saved to Keychain.
To use them, specify `--keychain-profile "NotarizationItemName"`
执行完之后, 去keychain里面查看一下:
之后 就可以通过在命令行里面直接调用--keychain-profile "NotarizationItemName"省去了输入
$AC_USERNAME和$AC_PASSWORD和$YourTeamId
2.2 : Upload的时候加上--wait
加上--wait代表要命令行在公正结束之后再返回, 可以在command output中看到Waiting for processing to complete., 并且可以在command output里直接查看到公证的结果.
~ % xcrun notarytool submit $ZipPath --keychain-profile "NotarizationItemName" --wait
Conducting pre-submission checks for $ZipName and initiating connection to the Apple notary service...
Submission ID received
id: ef09a19e-80a1-42b4-b1df-c937ae32a36c
Successfully uploaded file
id: ef09a19e-80a1-42b4-b1df-c937ae32a36c
path: $ZipPath
Waiting for processing to complete.
Current status: Invalid..........
Processing complete
id: ef09a19e-80a1-42b4-b1df-c937ae32a36c
status: Invalid
不加--wait命令行会马上返回一个requestID, 等待片刻可以用这个requestID来查询公正的结果.
xcrun notarytool submit $ZipPath --keychain-profile "NotarizationItemName"
Conducting pre-submission checks for $ZipName and initiating connection to the Apple notary service...
Submission ID received
id: c95d3c73-19d9-4b5f-8798-af08930002fb
Successfully uploaded file
id: c95d3c73-19d9-4b5f-8798-af08930002fb
path: $ZipPath
2.3 --webhook:
可以用在notarytool命令行后面加--webhook 并提供一个webhook url. 这样在公证完成之后会callback 到webexhook url, webexhook url 就会监听到公证job的submission ID, the team ID, and a signature, 客户端就可以来继续做后续的工作.
2.4 查询公证状态:
可以用xcrun notarytool history --keychain-profile "NotarizationItemName"来查询公证的历史记录.
xcrun notarytool history --keychain-profile "NotarizationItemName"
Successfully received submission history.
history
--------------------------------------------------
createdDate: 2021-04-29T01:38:09.498Z
id: 2efe2717-52ef-43a5-96dc-0797e4ca1041
name: OvernightTextEditor_11.6.8.zip
status: Accepted --------------------------------------------------
createdDate: 2021-04-23T17:44:54.761Z
id: cf0c235a-dad2-4c24-96eb-c876d4cb3a2d
name: OvernightTextEditor_11.6.7.zip
status: Accepted --------------------------------------------------
createdDate: 2021-04-19T16:56:17.839Z
id: 38ce81cc-0bf7-454b-91ef-3f7395bf297b
name: OvernightTextEditor_11.6.7.zip
status: Invalid
或者可以通过xcrun notarytool info来单个查询:
% xcrun notarytool info 809cf18c-d5b9-4c86-9d42-e1b1f91ef33d --keychain-profile "NotarizationItemName"
Successfully received submission info
createdDate: 2022-06-19T05:20:37.583Z
id: 809cf18c-d5b9-4c86-9d42-e1b1f91ef33d
name: $ZipName
status: Invalid
2.5 下载公证所得log
使用命令行xcrun notarytool log 可以下载公证的log到本地, 会返回下载好公证log的location
xcrun notarytool log 809cf18c-d5b9-4c86-9d42-e1b1f91ef33d --keychain-profile "NotarizationItemName" developer_log.json
Successfully downloaded submission log
id: 809cf18c-d5b9-4c86-9d42-e1b1f91ef33d
location: /Users/*/developer_log.json
通过这个log文件, 可以定位公证问题来解决.
2.6 绑定ticket到bundle
在MacOS 10.14之后, 当用户尝试在电脑上运行一个app时, GateKeeper会在线查找ticket. 通过ticket来判断app是否含有恶意成分.
公证完成之后, 会产生一个ticket, 我们需要将ticket 绑定到我们的app上, 从而不论电脑是否在联网的状态下Gatekeeper都能发现ticket, Gatekeeper就知道了我的app是公证过了, 是安全的.
之前在公证的时候我们提交的是zip, 当然我们也可以提交dmg或者pkg, 在绑定ticket时, 要将公证好的包解压出来, 再绑定.
xcrun stapler staple $APP_Name
Processing: $APP_Name
The staple and validate action worked!
2.7 验证ticket是否绑定成功:
stapler validate -v $APP_Name
3: 注意事项:
3.1 公证对网络的要求
notarytool默认使用Amazon S3来存储和计算, 他连接的是notary-submissions-prod.s3-accelerate.amazonaws.com 可以使用no-s3-acceleration来换一个如下面所示:
xcrun notarytool submit "$ZipPath" --keychain-profile "NotarizationItemName" --wait --no-s3-acceleration
如果你的网络配置不支持使用Amazon S3 那可以用之前公证方法的altool来公证.
xcrun altool --notarize-app --primary-bundle-id --username "$Your_AC_USERNAME" --password "$Your_ACPassword" --file "$ZipPath"
另外stapler 使用CloudKit(developer.apple.com/documentati…) 来download Ticket, 需要我们的build机器可以ping通下列的ip地址(均基于443端口):
- 17.248.128.0/18
- 17.250.64.0/18
- 17.248.192.0/19
3.2 有效的减小公证所用的时间
苹果声称大部分的软件, 公证在5分钟之内就可以完成, 但是仍有一部分软件公证需要花费很长的时间. 应该怎样有效的缩短公证所花费的时间呢?
WWDC21给出了几点建议:
- 1: 缩小提交bundle的
总数, 缩小bundle的体积 - 2: 非可执行文件例如: 图片/文件等等放在
MyApp.app/Contents/Resources/这个路径下, 苹果不会给Resources目录进行签名和公证, 所以会节省时间 - 3: 不要upload
损坏的dmg, 在提交之前可以用命令行hdiutil verify <image>验证包的完整性, 例如:
~ % hdiutil verify ~/Downloads/macOSPublicBetaAccessUtility.dmg
正在检查“Driver Descriptor Map (DDM : 0)”的校验和…
Driver Descriptor Map (DDM : 0):已验证CRC32 $27B36400
正在检查“ (Apple_Free : 1)”的校验和…
(Apple_Free : 1):已验证CRC32 $00000000
正在检查“Apple (Apple_partition_map : 2)”的校验和…
Apple (Apple_partition_map : 2):已验证CRC32 $9655363A
正在检查“disk image (Apple_HFS : 3)”的校验和…
...........................................................................................................................................................................................................................................................
disk image (Apple_HFS : 3):已验证CRC32 $288D4B0C
正在检查“ (Apple_Free : 4)”的校验和…
...........................................................................................................................................................................................................................................................
(Apple_Free : 4):已验证CRC32 $00000000
...........................................................................................................................................................................................................................................................
已验证CRC32 $234B6A72
hdiutil: verify: checksum of "~ /Downloads/macOSPublicBetaAccessUtility.dmg" is VALID
- 4: 避免高度压缩的磁盘映像
- 5: 避免提交巨大的、不可执行的数据文件,尤其是当它们经常更改时。
- 6: 将公证限制为每天 75 次之内
对于大bundle的upload, 苹果建议可以尝试从bundle中
抽出不可执行的文件。例如,如果要公证一个pkg,可以将pkg的内容拆分成不可执行文件和可执行文件, 可执行文件仍然保留在pkg中, 不可执行的文件移动到pkg旁边的文件夹中。然后将不可执行文件夹和经过公证的pkg放入一个dmg中,不经过公证的情况下release这个dmg就可以.