症状:Mac CI 仍显示签名成功,但你不确定它用的是旧 Sub-CA 证书,还是已经换成 G2。 最快解法:先查签名证书的 Issuer,再按用途替换受影响证书,并在隔离 Mac CI 中验收签名、公证和最终交付物;旧证书签署的受影响安装包须在 2027 年 2 月 1 日前重新签名,已公证且带安全时间戳的 Mac 应用无需仅因这次到期重签。(Apple 到期公告)
这篇适合维护 macOS 应用 Developer ID 签名、分发和公证流程的工程师;你需要确认签发方并安排替换计划。
如果你负责 Mac CI 节点或密钥链,要验证新证书确实能被流水线执行账户调用。
如果你负责发布,则重点区分 .pkg 与已公证 Mac 应用的影响范围,避免全量重签或漏掉安装包。
最后更新于 2026 年 11 月 7 日;日期、证书替换步骤及交付范围核实自 Apple 到期公告、证书替换指南和 Developer ID 证书说明。
先盘点 Mac CI 实际调用的证书
不要先看到到期日期就批量创建、撤销或替换证书。Apple 提醒,日期只能作为筛查线索;确认是否受影响,要检查签名证书本身的签发方。Keychain 中另有中间证书条目,查看错对象可能把证书颁发机构误认成签名证书。(Developer ID 证书替换指南)
按流水线逐项登记下列内容,记录证书用途、签发方、对应的构建任务、执行账户、密钥链和发布产物:
- 在开发者账户的 Certificates 页面,分别检查 Developer ID Application 与 Developer ID Installer。
- 在 Mac 的 Keychain Access 中找到对应的 Developer ID 叶证书,展开 Issuer Name,检查 Organizational Unit。
- 如果该字段显示 Apple Certification Authority,属于旧 Sub-CA 签发的证书,应纳入替换清单;显示 G2 则属于当前 Sub-CA。
- 在 CI 配置与签名脚本中确认实际选用的身份;不能只看账户里存有哪张证书,还要检查任务实际访问的 keychain 和私钥。
- 把历史发布产物、当前流水线产物和待发布产物分开记录,避免把“账户有新证书”误当作“流水线已经切换”。
| 交付对象 | 负责的证书 | 旧 Sub-CA 到期时的判断 | 处理方向 |
|---|---|---|---|
| Mac 应用及其嵌套代码 | Developer ID Application | 已签名、公证且含安全时间戳的既有应用无需仅因本次到期重签 | 后续版本切换到 G2,并复验签名、公证与时间戳 |
Installer 安装包 .pkg | Developer ID Installer | Apple 公告指出,受影响证书签署的安装包届时将不能安装 | 用新的 Installer 证书重新签名,并在截止日前替换受影响包 |
| 应用与安装包混合交付 | 两类证书各自负责对应对象 | 不能用一种证书代替另一种,也不能只检查应用签名 | 分别登记、替换并验收两条签名链 |
按交付物划定到期影响
Developer ID G2 证书过期对 Mac CI 的影响,不等于所有应用都要重签。 Apple 已公告,原 Developer ID Certification Authority(Sub-CA)于 2027 年 2 月 1 日到期,届时该机构签发的证书将停止工作;对安装包与既有应用必须分开判断。
对 .pkg,按 Apple 公告执行:受影响旧证书签署的包需要在截止日前用新证书重签并替换。已有安全时间戳且已公证的 Mac 应用,按公告无需仅因为这次 Sub-CA 到期而重签;但后续更新仍要切换到有效的新证书,并按发布流程签名和公证。请不要把“既有应用无需重签”扩展成“所有安装包均无需处理”,也不要把签名证书过期、Sub-CA 到期和证书撤销混为一谈。
先创建 G2 替换证书,再安排密钥交接
在 Certificates, Identifiers & Profiles 中,按实际用途分别申请 Developer ID Application 和 Developer ID Installer。若团队两种证书都在使用,就分别创建和登记;一张 Application 证书不能签 Installer 包,反过来也一样。创建替换证书时,如果页面要求选择 Developer ID Certificate Intermediary,选择 G2 Sub-CA。
Apple 的替换指引要求使用 Xcode 11.4.1 或更新版本来选择 G2 Sub-CA;如果你仍依赖更早的 Xcode,不要靠试签猜测颁发结果,先按 Apple 现行指南更新创建证书所用工具,再检查新证书的 Issuer。G2 颁发的叶证书按年度到期并需续期,这与 Sub-CA 自身的有效期不是一回事;把这项复核加入证书管理日历。
交接时将证书文件、对应私钥、安装位置、CI 凭据负责人和回退责任写清楚。证书文件本身不等于可签名的完整身份;如果私钥没有随受控流程安装到任务实际使用的 keychain,流水线可能找不到身份或无法完成签名。不要把私钥或 keychain 密码直接写入脚本、构建日志或工单。
在隔离 Mac CI 任务中试签与公证
隔离验收的重点不是“在某台 Mac 上手动签过”,而是确认正式任务相同的执行账户、签名设置和凭据路径能够使用新证书。团队暂时没有适合试跑的 Mac 环境时,可先了解 远程 Mac 开发环境 的使用方式;是否适合你的签名验收,还要看密钥管理与实际权限要求,不能预设服务已具备某种托管能力。
建议在不发布给用户的分支或隔离任务中按以下顺序操作:
- 安装新证书及匹配私钥,确认 CI 执行账户能访问指定 keychain 和签名身份。
- 使用正式流水线的构建配置生成应用或安装包,记录实际使用的证书名称与构建任务。
- 对应用运行
codesign --verify --deep --strict,同时检查签名详情、嵌套代码和安全时间戳;不能只凭构建命令退出成功判断签名完整。 - 按既有流程提交公证,并分别记录提交编号、最终状态及结果日志。Apple 的命令行公证工作流说明区分了上传、查询结果与票据处理;提交成功不等于公证最终通过。
- 对最终要分发的产物执行对应验证,并将命令输出、证书 Issuer、构建版本和产物校验值留档。Apple 的代码签名检查指南说明了代码签名检查与系统策略评估的不同用途;签名有效不能替代公证结果核验。
对照产物逐项验收
验收时既要看证书,也要看最终交付物。签名可能发生在构建之后、打包之前或发布脚本中;只在 Keychain 里看到 G2 证书,不能证明产物确实由它签署。
| 验收对象 | 建议保留的证据 | 评分 |
|---|---|---|
应用 .app | codesign 验证结果、签名身份与 Issuer、时间戳检查、公证最终状态 | ✅ 完整;缺 Issuer 或公证最终结果则 ⚠️ 待补 |
安装包 .pkg | pkgutil --check-signature 输出、Developer ID Installer 身份、公证结果及最终包版本 | ✅ 完整;仍使用受影响旧身份则 ❌ 阻断 |
| 流水线执行环境 | 实际执行账户、keychain 访问与凭据调用记录、任务日志 | ✅ 任务可重复调用;仅本机手动成功则 ❌ 未通过 |
codesign --verify --deep --strict <应用路径> 检查签名,再用 spctl --assess --type execute <应用路径> 检查系统策略评估;如工作流会装订公证票据,还应对分发版本运行 xcrun stapler validate <应用路径>。命令通过也不应覆盖公证状态、证书 Issuer 和时间戳的单独核验。
对 .pkg,用 pkgutil --check-signature <安装包路径> 检查 Installer 签名,并确认身份来自替换后的 Developer ID Installer 证书。对受影响旧证书签署的包,必须安排重签和替换;是否重新提交公证,则按团队的包发布工作流执行并记录最终结果。Apple 的 Developer ID 签名说明列出可用于自定义流程的 notarytool 与 stapler 工具;不要把工具返回的单一状态当成完整验收记录。
出现以下任一情况,应判为阻断发布:流水线选中的身份仍由旧 Sub-CA 签发;Installer 包仍使用旧证书;公证只有提交记录而没有最终结果;或产物验证与 CI 日志指向不同构建版本。补齐证据后再重跑隔离任务,不要先推广到全部正式节点。
正式推广与到期复核
隔离任务通过后,再逐个更新正式 Mac CI 节点的签名身份引用。先保留可回退的发布路径和旧构建记录,确认新任务能生成符合预期的应用及安装包,再扩大切换范围。不要因为新证书已经创建,就立刻撤销仍服务于回退或在途发布的证书;撤销会改变其可用状态,应单独走权限和影响评估流程。
每次推广至少留存:证书用途与 Issuer、CI 节点和执行账户、实际签名身份、公证最终状态、产物版本及回退负责人。随后在开发者账户中复核证书签发方和有效期,并把 G2 叶证书的年度续期纳入提醒;Sub-CA 有效期与叶证书续期周期不同,不能用其中一个日期代替另一个检查。
常见问题
怎样判断 Mac CI 用的是哪个 Sub-CA?
在 Keychain Access 检查 CI 实际使用的 Developer ID 叶证书,展开 Issuer Name 并查看 Organizational Unit;旧 Sub-CA 显示 Apple Certification Authority,当前证书显示 G2。再对照构建配置和 keychain,确认检查的证书正是流水线所选身份,而不是同名的中间证书。
替换 G2 证书后,验收要覆盖哪些环节?
在隔离 Mac CI 中验证任务实际执行账户能调用证书和私钥,随后检查签名身份、代码签名结果、安全时间戳、公证提交与最终处理状态,并针对实际交付物运行相应检查。任一环节只在本机手动通过、却没有流水线证据,都不能作为 CI 验收完成的依据。
受影响的 Developer ID Installer 安装包如何处理?
确认 .pkg 的签名身份确由旧 Sub-CA 签发后,用新的 Developer ID Installer 证书重签,并在 2027 年 2 月 1 日前完成受影响包的替换。不要用 Developer ID Application 证书替代 Installer 证书;公证状态也应按团队实际发布流程另行提交和核验。
已公证的 Mac 应用要因为旧 Sub-CA 到期而重签吗?
如果应用已签名、公证且包含安全时间戳,Apple 的到期公告说明它无需仅因本次 Sub-CA 到期而重签。这个结论针对公告所说的既有 Mac 软件,不应套用到受影响的 .pkg;后续应用版本仍应使用 G2 证书完成签名与公证验收。
如果你的团队目前依靠一台开发者本机完成所有签名验收,常见短板是任务无法复现、执行账户与 CI 不一致、发布节点难以持续在线。需要临时增加隔离验收环境时,可比较自有 Mac、现有构建节点与远程租赁的运维边界;若只是短期验证,可查看 MACGPU 的 Mac 环境方案,但签名私钥是否适合放入该环境,仍应由你按团队安全策略评估。若你需要长期固定负载、物理接口或严格限定密钥不得离开自有设备,优先使用自有 Mac。核心操作不变:先核对 Issuer,再分别处理应用与安装包,并以隔离 Mac CI 的完整证据决定是否放行。