扩展包发布不再存长期令牌:Trusted Publishing 的信任边界怎么划
微软为 Visual Studio Marketplace 上线 Trusted Publishing,GitHub Actions 与 Azure Pipelines 可以在不保存长期 PAT 的情况下发布扩展。文章拆开两条路径的信任边界:GitHub 侧由仓库、工作流与环境字段构成策略匹配,Azure 侧依赖 Entra 支持的 WIF 身份加发布者 Contributor 角色;并说明迁移顺序、私有仓库 48 小时激活窗口,以及边界之外仍需自管的环节。
- 信任边界从“持有 PAT 的人”移到“被策略匹配的仓库 + 工作流(+ 可选环境)”;Azure 侧则移到“被授予 Co
- 迁移要先让 OIDC 或 WIF 发布跑通,再删 PAT;公告建议保留旧凭证直到首次成功。
- 凭证变短命不等于风险归零:能改工作流的人、id-token 权限范围、构建产物完整性仍在边界之内。
Trusted Publishing 把扩展发布的信任边界,从“谁拿到长期令牌”改成了“哪条被显式登记的工作流、以什么身份、在多长时间内发起发布”。按微软 2026 年 10 月 28 日的公告,Visual Studio Marketplace 现在支持从 GitHub Actions 或 Azure Pipelines 发布 Visual Studio Code 与 Visual Studio 扩展,CI/CD 里不必再保存长期有效的 Azure DevOps 个人访问令牌(Personal Access Token,PAT)。这是边界收窄,但不是把所有边界都消掉——剩下的一段仍然落在 CI/CD 平台和工作流本身。Microsoft for Developers 公告
先看结论:边界挪到了哪里#
旧做法里,PAT 是一种持有即可用的凭证。它被复制进仓库 secret,任何能读到这个 secret 的工作流步骤都能拿它发布;泄露之后的可用窗口,等于令牌有效期减去吊销所需的时间。新的做法把“可用”拆成两步:CI/CD 系统先向 Marketplace 出示联合身份,Marketplace 验证通过后,发布动作才被放行。公告给出的关键点是,GitHub Actions 场景下 Marketplace 签发的临时凭证 15 分钟后过期,因此没有需要保存或轮换的发布密钥。
换句话说,被信任的对象变了:不再是一串可以复制走的字符串,而是一次能通过策略匹配的身份交换。这决定了后面所有配置的重点——策略字段写得准不准,比令牌藏得好不好更关键。
两条路径,边界画法不一样#
公告把 GitHub Actions 和 Azure Pipelines 并列为受支持,但两者的信任锚点并不相同。这一点最容易在迁移时搞混。
| 维度 | GitHub Actions | Azure Pipelines |
|---|---|---|
| 身份来源 | GitHub OIDC | 由 Microsoft Entra 支持的 WIF 服务连接,底层可以是应用注册加服务主体,也可以是托管身份 |
| Marketplace 侧动作 | 在发布者的 Trusted Publishing 页创建策略 | 把该身份加为发布者,并授予 Contributor 角色 |
| 是否需要 Marketplace 策略 | 需要 | 不需要;公告明确说不要为 Azure Pipelines 创建策略 |
| 临时凭证寿命 | 15 分钟 | 本次材料未给出,待核实 |
| 可发布的扩展类型 | VS Code 与 Visual Studio 扩展 | VS Code 与 Visual Studio 扩展 |
Azure Pipelines 走的是另一条信任链:信任建立在 Entra 身份与发布者成员关系上,Marketplace 不参与工作流级别的策略匹配。因此,“在 Marketplace 建策略”这一步对 Azure 是多余动作,做了反而容易让人误以为两套机制可以叠加。
GitHub 策略的字段,就是边界的刻度#
策略不是一句“允许发布”的开关,而是一组精确匹配条件。公告列出的创建字段包括:
- 策略名称:描述性名称,例如 Release workflow,只用于识别,不参与匹配。
- 仓库所有者:拥有仓库的 GitHub 组织或用户登录名,需精确填写。
- 仓库:不含所有者的仓库名。
- 工作流:
.github/workflows下的文件名,例如publish.yml。 - 环境(可选):工作流使用 GitHub 环境时填写其精确名称,例如
production。
这几个字段合起来,等于在说“只有这个仓库里的这个工作流文件,才被允许换到发布凭证”。环境字段留空与填写的差别,不只是多一个输入框:填写之后,匹配范围收窄到使用该环境的作业。至于环境本身是否带审批或保护规则,取决于 GitHub 侧的配置,不在 Marketplace 策略的语义里。
材料没有说明策略是否支持分支维度的匹配。如果发布只允许从默认分支触发,这一点需要以官方文档为准,不能想当然地认为“工作流文件名匹配”已经覆盖了分支限制。
私有仓库的 48 小时窗口
公告对私有仓库给了一个容易忽略的机制:新建策略后处于临时激活状态,有效期 48 小时;第一次成功的令牌交换会让策略永久激活。若这 48 小时内没有使用,策略会过期,可以重新打开另一个 48 小时窗口。策略的状态与最近使用时间,可以在 Trusted Publishing 页面查看。
这个设计的实际含义是:私有仓库的首次迁移要在一个相对紧凑的时间窗里完成,而不是建完策略放置数周再回来接流水线。公开仓库没有这条限制的描述。
迁移顺序:先走通新路,再关旧门#
公告给出的 GitHub Actions 迁移步骤,顺序本身就体现了边界收缩的逻辑:
- 为对应仓库和工作流创建 Trusted Publishing 策略。
- 在发布作业上添加
id-token: write权限。 - 把发布命令改为使用 OIDC。
- 运行工作流,确认 OIDC 发布成功。
- 成功之后,再从工作流和仓库 secret 中移除 Marketplace PAT。
公告特别建议:在第一次 Trusted Publishing 跑通之前保留 PAT;迁移成功后删掉未使用的 secret,避免它被其他工作流步骤误用。这一步不是形式主义——只要 secret 还在,任何能引用它的步骤都仍处在旧的信任边界内。
下面是一个仅用于说明权限位置的片段,未执行,发布命令请按 VS Code 文档中的 “Secure automated publishing to Visual Studio Marketplace” 指南填写:
# 未执行示例:仅示意 OIDC 权限应加在发布作业上
name: publish-extension
on:
workflow_dispatch:
jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write # 允许该作业向 GitHub 请求 OIDC 令牌
steps:
- uses: actions/checkout@v4
# 其余步骤按官方 VS Code 文档配置,本文未验证具体命令
Azure Pipelines 的顺序不同,因为没有策略这一步:先配置使用工作负载身份联合(Workload Identity Federation,WIF)的服务连接,把该身份加入 Marketplace 发布者并授予 Contributor,再把发布步骤改为使用这个连接;只有联邦发布成功之后,才移除 PAT。公告同样强调不要为 Azure 创建 Marketplace 策略。
边界收窄之后,还在边界内的东西#
不再存长期令牌,解决的是“凭证被复制走”这一类风险。但发布链路上还有几段没有被这次改动覆盖,值得单独看:
- 谁能改工作流。策略匹配的是工作流文件,那么能修改该文件、能向默认分支合入改动、能触发手动运行的人,实际上就能定义“可信发布”的内容。这是迁移后最需要重新审视的权限面。
id-token: write的授予范围。公告的表述是给发布作业添加该权限;从最小权限的角度,建议只加在发布作业上,而不是整个工作流,避免无关步骤也能请求 OIDC 令牌。这是基于权限模型的推断,不是公告原文。- Azure 侧的 Contributor 角色。公告只说把身份加为发布者并授予 Contributor,未给出更细的角色粒度或作用范围说明,待核实。
- 构建产物与依赖。Trusted Publishing 回答的是“谁有资格发布”,不回答“发出去的东西是不是你构建的那一份”。依赖锁定、构建可复现性仍需另行管理。
- 审计信息。策略状态和最近使用时间可查,但材料未说明发布审计日志保留多久、包含哪些字段,待核实。
什么时候先别急着迁#
有三种情况适合先等一等:私有仓库且短期内无法在 48 小时窗口内跑通首条流水线;发布流程横跨多个仓库或多个工作流,策略还需要拆分设计;以及没有准备好回退方案。公告明确说,基于 PAT 的发布方式继续可用,所以“暂不迁移”本身也是一个合理的边界选择,只要清楚旧边界仍然存在。
如果决定迁移,回退方案可以很简单:首次 OIDC 发布验证通过之前不移除 PAT;验证通过后立即移除,并确认没有其他工作流仍在引用该 secret。
把三处配置对齐#
信任边界不是一个开关,而是三处配置的合力:Marketplace 侧的策略字段、CI/CD 侧作业的令牌权限、以及发布者成员的角色分配。任何一处比预期宽,边界就跟着变宽。迁移完成后,值得回头核对一遍这三处,而不是只确认“发布成功了”。
参考来源
以上为本文写作时的参考资料,引用观点以原文为准。