[WWDC21]公证(Notarization)流程的更新

4,141 阅读4分钟

公证系列:

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公证代码如下:

截屏2022-06-20 23.59.30.png

公证的过程图:

截屏2022-06-21 09.54.47.png

1.2: 新的公证workflow

WWDC21中, 苹果为了降低公证的复杂度引入了notarytool用来替换之前的xcrun,可以通过一个命令行直接查询到公证结果, 使公证更快更容易.

除了开发者使用notarytool这一个改动, 苹果也精简了notarization service. 苹果构建了一个新的专用Notarization的server, 该server为Notary提供更大的可靠性, 并且会使upload bundle的速度提升四倍.

2: notarytool的使用

2.1 将AC_USERNAMEAC_PASSWORD存在keychain

为了避免在命令行中明文使用AC_USERNAMEAC_PASSWORD, 苹果在WWDC21里提供了一个命令行可以将AC_USERNAMEAC_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里面查看一下:

截屏2022-06-20 15.44.55.png

之后 就可以通过在命令行里面直接调用--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就可以.