Highlight
Apple 给 macOS App 公证提供了三条迁移路径:altool 在 2023 年秋季停止用于公证,Xcode 14 接入 notarytool 后端,新的 Notary REST API 支持从 Linux 等 CI 环境提交和查询公证任务。
核心内容
Mac App 如果不走 App Store 分发,开发者通常要做 Developer ID 签名和公证。公证服务会分析上传的软件,帮助 macOS 在用户下载第三方软件时拦截恶意内容。
这套流程以前常见的痛点有两个。
第一,旧脚本还在调用 altool。团队要维护凭据、上传、等待结果和错误处理。第二,CI 机器不一定是 Mac。比如 Linux 构建节点可以产出归档文件,却不能直接运行 Xcode 或 notarytool 完成后续流程。
这场 session 给出明确迁移路线:旧的 altool 公证和 Xcode 13 UI 上传会在 2023 年秋季停止工作;Xcode 14 的图形流程改用 notarytool 同一套后端;新的 Notary REST API 让任何能联网的机器都能提交文件、查询状态、获取历史记录和详情。
详细内容
altool 退场,notarytool 继续可用
(01:11)Apple 在 2021 年发布了 notarytool,作为 altool 公证流程的替代。2022 年这场 session 给出截止日期:使用 altool 做公证会在 2023 年秋季停止工作。Xcode 13 UI 上传到公证服务也会在同一截止日期后停止。
notarytool 本身会继续工作,包括 Xcode 13 内置的版本。Apple 仍建议升级,以获得最新修复和改进。
# 概念示意:旧脚本需要从 altool 迁到 notarytool
# 具体参数以 2021 年 “Faster and simpler notarization for Mac apps” 和文档为准。
# before: xcrun altool ...
# after: xcrun notarytool ...
关键点:
- 第一行说明这是迁移提示,不是本场 session 给出的完整命令。
altool是需要迁出的旧路径。notarytool是 2023 年秋季之后仍可继续使用的命令行路径。- 具体迁移细节在 Apple 引用的 WWDC 2021 session 中展开。
Xcode 14 把图形流程接到 notarytool 后端
(02:30)如果团队使用 Xcode Organizer 上传公证,迁移压力更小。Xcode 14 的内置公证支持迁到了和 notarytool 相同的后端,因此能获得 Apple 在 2021 年为 notarytool 宣布的约 4 倍性能提升。
这部分的重点是“不改工作流”。演讲明确说,除了更新 Xcode,通常不需要改变项目设置或现有流程。
Xcode 13 UI notarization -> stops working after fall 2023
Xcode 14 UI notarization -> uses the notarytool backend
notarytool CLI -> continues past the deadline
关键点:
Xcode 13 UI notarization对应演讲中会在截止日期后停止工作的旧 UI 上传方式。Xcode 14 UI notarization对应新的 Xcode 集成。notarytool backend是 Xcode 14 获得性能提升的原因。notarytool CLI仍是自动化脚本可使用的迁移目标。
Notary REST API:先创建提交,再上传到 S3
(03:01)新的 Notary REST API 是这场 session 的主角。它是 JSON Web 服务,使用 JSON Web Token(JWT)认证,和其他 App Store Connect API 类似。它的目标是让不运行 macOS 的机器也能和公证服务交互。
上传分两步。第一步,把文件名和 SHA-256 发给 Notary API。服务返回临时 S3 凭据、bucket、object,以及一个用于跟踪流程的 submission_id。第二步,用 S3 SDK 把文件上传到 Apple 提供的位置。
# Upload file for notarization
def upload_file(token, filepath, sha256):
data = { "sha256": sha256, "submissionName": os.path.basename(filepath) }
resp = requests.post(
"https://appstoreconnect.apple.com/notary/v2/submissions",
json=data,
headers={"Authorization": "Bearer " + token})
output = resp.json()
aws_info = output["data"]["attributes"]
submission_id = output["data"]["id"]
client = boto3.client(
"s3",
aws_access_key_id=aws_info["awsAccessKeyId"],
aws_secret_access_key=aws_info["awsSecretAccessKey"],
aws_session_token=aws_info["awsSessionToken"])
client.upload_file(filepath, aws_info["bucket"], aws_info["object"])
关键点:
upload_file(token, filepath, sha256)把 JWT、文件路径和文件哈希作为输入。data只包含演讲里提到的基础文件信息:SHA-256 和提交名称。requests.post(...)调用 Notary REST API 的 submissions endpoint。Authorization: Bearer ...使用 JWT 认证。aws_info保存响应中的临时 S3 上传信息。submission_id是后续查询公证状态的 ID。boto3.client("s3", ...)用返回的临时凭据创建 S3 客户端。client.upload_file(...)把文件上传到响应指定的 bucket 和 object。
这段代码也说明了 REST API 的边界:Notary API 不直接接收整个文件。它先创建提交并返回上传信息,文件内容再走 Amazon S3。
查询状态:等待 In Progress 变成最终结果
(06:12)上传之后,分发前要确认公证服务已经处理完提交。REST API 的直接做法是用 submission_id 查询状态。状态会保持 In Progress,直到处理完成后变为最终状态,例如 Accepted 或 Invalid。
# Wait for completion
def watch_upload(submission_id, token):
while True:
resp = requests.get(
"https://appstoreconnect.apple.com/notary/v2/submissions/" + submission_id,
headers={"Authorization": "Bearer " + token})
output = resp.json()
current_status = output["data"]["attributes"]["status"]
if current_status != "In Progress":
return current_status # For example: Accepted or Invalid
time.sleep(30) # Allow time for submission to progress
关键点:
watch_upload(submission_id, token)用上传阶段拿到的提交 ID 继续跟踪同一次提交。requests.get(...)访问单个 submission 的 Notary API endpoint。Authorizationheader 继续使用同一个 JWT 认证方式。current_status读取响应里的当前处理状态。current_status != "In Progress"表示公证服务已经给出最终结果。Accepted和Invalid是演讲中列出的最终状态示例。time.sleep(30)避免持续请求;演讲示例用 30 秒等待提交推进。
演讲还补充,提交完成后,可以通过 API 获取这次上传的公证日志。具体 endpoint 需要看 Notary API 文档。
Webhook:把上传系统和后续自动化解耦
(06:49)轮询不是唯一选择。Notary REST API 也支持 webhook 工作流:初始上传请求里提供 webhook URL,自动分析结束、票据创建、最终状态保存后,公证服务会调用这个 URL。
演讲明确说明,通知内容包含 submission ID、team ID 和一个用于验证通知来自 Apple 的签名。
upload request includes webhook URL
│
▼
notary service analyzes submission
│
▼
tickets are created and final status is saved
│
▼
notary service calls webhook URL
│
├─ submission ID
├─ team ID
└─ signature
关键点:
webhook URL是在初始上传请求中提供的回调地址。analyzes submission对应公证服务对上传文件的自动分析。tickets are created对应演讲中分析完成后创建 ticket 的步骤。final status is saved表示服务端已经有最终公证状态。submission ID和team ID让接收方知道是哪次提交、哪个团队。signature用来验证通知来源。
这个模型适合 CI/CD。上传机器只负责提交文件。另一个系统收到 webhook 后,可以通知提交者,也可以启动自动分发流程。两部分不必用同一个进程等待。
核心启发
-
做什么:把仍在使用
altool的 CI 脚本列出来,逐个迁移到notarytool或 Notary REST API。
为什么值得做:altool 公证会在 2023 年秋季停止工作,迁移是硬性期限。
怎么开始:先找构建日志里的altool调用,再按是否能运行 macOS 选择notarytool或 REST API。 -
做什么:给 Linux 构建节点增加一个公证上传步骤。
为什么值得做:REST API 支持从任何联网机器提交,不再要求上传步骤运行在 Mac 上。
怎么开始:用 JWT 调用POST https://appstoreconnect.apple.com/notary/v2/submissions,拿到 S3 信息后用现有语言的 S3 SDK 上传文件。 -
做什么:为公证结果建立 webhook 回调服务。
为什么值得做:webhook 可以把上传流程和后续通知、分发流程拆开,减少长时间轮询任务。
怎么开始:在初始提交请求中配置 webhook URL;接收通知后校验签名,再根据submission ID查询或触发后续动作。 -
做什么:把公证状态和日志接入内部发布面板。
为什么值得做:REST API 支持查询提交状态、历史记录、提交详情和公证日志,发布人员不用只看 CI 控制台。
怎么开始:保存每次上传返回的submission_id,定时或按需调用 Notary API 展示状态和日志链接。
关联 Session
- Faster and simpler notarization for Mac apps — 2021 年介绍
notarytool,是理解本场迁移期限的前置内容。 - What’s new in App Store Connect — 同年讲 App Store Connect 和 API 自动化更新,适合一起看发布工具链的变化。
- Deep dive into Xcode Cloud for teams — 展开团队 CI/CD、App Store Connect API 和自动化集成场景。
评论
GitHub Issues · utterances