ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Lerna 与 npm OIDC 可信发布(Trusted Publishing)实战指南

Lerna 与 npm OIDC 可信发布(Trusted Publishing)实战指南 Lerna 与 npm OIDC 可信发布Trusted Publishing实战指南【免费下载链接】lernaLerna is a fast, modern build system for managing and publishing multiple JavaScript/TypeScript packages from the same repository.项目地址: https://gitcode.com/gh_mirrors/le/lernaLerna 9.0.0 起原生支持 npm 的 OIDC 可信发布Trusted Publishing允许从 GitHub Actions、GitLab CI、CircleCI 等受信任 CI 环境直接发布包不再依赖传统固定 Token。本文围绕这一能力讲解其核心原理、零配置接入方式并结合本仓库源码剖析 OIDC Token 的获取、交换与 provenance软件供应链溯源自动开启机制。什么是 OIDC 可信发布OIDCOpenID Connect可信发布是 npm 推出的一种安全发布方案不再使用传统 Token 或固定凭据而是允许你在 npm 侧配置某个包只允许从特定受信任环境如 GitHub Actions、GitLab CI发布。在这些受支持的 CI 环境中发布时动态获取 OIDC Token用它换取 npm 注册表的短期访问凭证来执行发布发布动作完成即失效从而显著降低凭据泄露风险。Lerna 在v9.0.0中加入了对此方案的支持。核心承诺是如果你按照 npm 官方的可信发布指南配置好你的流水线那么它对 Lernav9 及之后版本同样开箱即用无需任何额外配置。也就是说OIDC 在 Lerna 中是可选增强能力不会干扰原有基于 Token 的发布流程。支持的 CI 环境从 oidc.ts 的源码注释与实现看Lerna 的 OIDC 支持覆盖三种主流 CIGitHub Actions通过请求式接口获取 ID TokenGitLab CI通过环境变量提供 ID TokenCircleCI同样通过环境变量提供 ID Token。关键限制是这段逻辑被设计为只在 CI 环境中运行。源码通过ci-info库检测ciInfo.GITHUB_ACTIONS || ciInfo.GITLAB || ciInfo.CIRCLE如果当前环境不是这三者之一函数直接返回undefined不做任何 Token 交换。这保证了开发者在本地机器上手动执行lerna publish时OIDC 逻辑不会介入行为与旧版本完全一致。在 GitHub Actions 中的完整接入示例下面是一份可直接套用的工作流骨架GitHub Actions npm Lerna v9核心在于permissions中授予id-token: writename: publish on: push: tags: - v* permissions: contents: read id-token: write # OIDC 可信发布的必要条件 jobs: publish: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 - uses: actions/setup-nodev4 with: node-version: 20 registry-url: https://registry.npmjs.org/ - run: npm ci - run: npx lerna publish from-git --yes配合 npm 侧的 Trusted Publishers 配置把你的 GitHub 仓库 / 工作流注册为该包的受信任发布者即可实现无需NPM_TOKEN的安全发布。为什么必须设置 id-token: writeLerna 从 CI 获取 ID Token 的方式取决于环境变量。以 GitHub Actions 为例源码要求同时存在两个由 GitHub 注入的环境变量ACTIONS_ID_TOKEN_REQUEST_URL请求 ID Token 的地址ACTIONS_ID_TOKEN_REQUEST_TOKEN请求 ID Token 时用于认证的 Token。而这两个变量只有在工作流声明了permissions: id-token: write时才会出现。如果缺少该权限源码会记录Skipped because incorrect permissions for id-token within GitHub workflow并跳过 OIDC此时发布会退化为普通流程若没有其他凭据则会失败。audience 的构造规则GitHub Actions 的 OIDC 请求需要指定 audience源码中的规则为npm:registry hostname即对https://registry.npmjs.org/会生成npm:registry.npmjs.org如果通过--registry或publishConfig.registry指向其他受支持的注册表例如 Verdaccio 等私有 registryaudience 会相应变为npm:该注册表主机名以满足registry.npmjs.org 可为任意受支持注册表的规范。GitLab CI / CircleCI 的接入方式与 GitHub Actions 不同GitLab CI 与 CircleCI 的 ID Token 通过环境变量直接注入源码读取的是NPM_ID_TOKEN在 GitLab CI 中NPM_ID_TOKEN是官方预定义的环境变量名你需要按 GitLab 文档在id_tokens配置块中声明在 CircleCI 中需在项目设置中启用 OIDC Token 并将其以NPM_ID_TOKEN命名注入环境。值得注意的细节NPM_ID_TOKEN这个命名遵循了 sigstore 的SIGSTORE_ID_TOKEN前缀/后缀约定见源码注释。另外即使是在 GitHub Actions 中如果环境变量里已存在NPM_ID_TOKEN它也会优先于请求式获取方式——源码先读取NPM_ID_TOKEN只有为空时才走ACTIONS_ID_TOKEN_REQUEST_URL请求流程。Lerna 的 OIDC 实现原理源码级解读Lerna 的 OIDC 逻辑位于 libs/core/src/lib/oidc.ts整体流程如下CI 检测仅当GITHUB_ACTIONS/GITLAB/CIRCLE任一为真时才继续获取 ID Token优先读NPM_ID_TOKEN环境变量GitHub Actions 下则按audience npm:registry hostname请求ACTIONS_ID_TOKEN_REQUEST_URL换取 JSON 中的value字段Token 交换调用 npm registry 的/-/npm/v1/oidc/token/exchange/package/escapedPackageName接口POST请求头以 ID Token 作为认证 Token写入凭据交换成功后把短期 Token 同时写入opts[authTokenKey]和config_authToken供后续libnpmpublish的发布请求使用自动开启 provenance若仓库为 public则自动启用软件供应链溯源见下文。Token 交换的 URL 形如https://registry.npmjs.org/-/npm/v1/oidc/token/exchange/package/scope%2fpkg注意包名会经过npa().escapedName转义例如作用域包的/被编码为%2f这一点由 oidc.spec.ts 中的测试用例验证expect(registryFetchJson).toHaveBeenCalledTimes(1); expect(registryFetchJson.mock.calls[0][0].toString()).toBe( https://registry.npmjs.org/-/npm/v1/oidc/token/exchange/package/scope%2fpkg );调用链从 lerna publish 到 OIDC在 libs/commands/publish/src/index.ts 的发布流水线中每个包最终会走到 npmPublish。npmPublish在真正调用libnpmpublish的publish()之前会先执行await oidc({ packageName: pkg.name, registry: opts.registry ?? https://registry.npmjs.org/, opts, config: conf, });registry 的默认值是https://registry.npmjs.org/可通过 CLI 的--registry参数或各包package.json的publishConfig.registry覆盖publishConfig会在调用前合并进opts。整个函数被设计为永不抛出异常——任何一步失败权限不足、交换失败、响应缺 Token都只记录 verbose 日志并返回OIDC 始终是可选增强不会阻断发布流程。自动 provenance公开仓库的软件供应链溯源OIDC 实现中还内建了provenance来源证明自动开启逻辑这是 npm 软件供应链安全SLSA能力的一部分。源码会解码 ID Token 的 JWT payload然后按以下条件判断GitHub Actionspayload 中repository_visibility public且通过libnpmaccess.getVisibility确认包当前为公开可见时自动把opts.provenance true写入发布选项GitLab CI要求 payload 中project_visibility public且环境变量SIGSTORE_ID_TOKEN存在才会开启 provenance。也就是说私有仓库不会触发 provenance这是刻意为之的安全边界。开启 provenance 后发布产物会附带可验证的构建来源声明由 npm 的 sigstore 基础设施签名并生成对应的透明度日志 URL。由于libnpmpublish不直接暴露 provenance 数据Lerna 在 publish 命令的源码 中通过监听process.on(log)事件、匹配包含provenance statement和https://的日志行来收集透明度日志链接并在发布结束后统一输出The following provenance transparency log entries were created during publishing: - https://透明度日志 URL这让你在 CI 日志中一眼确认每个包都产出了可审计的来源证明。常见问题与排查要点本地发布不受影响OIDC 逻辑仅在三类受支持 CI 中生效本地手动发布走传统凭据路径GitHub Actions 下没有 OIDC 行为优先检查工作流是否声明了permissions: id-token: write缺少该权限时日志会出现Skipped because incorrect permissions for id-token within GitHub workflowGitLab 下 provenance 未生效确认项目为 public且已注入SIGSTORE_ID_TOKEN环境变量私有 registryaudience 会按npm:registry hostname动态生成但 Token 交换接口、可信发布者配置均需目标 registry 支持 OIDC 能力想查看 OIDC 细节日志可使用 verbose 日志级别相关日志前缀为oidc例如Skipped because no id_token available、Successfully retrieved and set token。小结OIDC 可信发布让 Lerna 用户在不维护传统 npm Token 的前提下也能在 GitHub Actions、GitLab CI、CircleCI 中安全发布多包仓库。只要 npm 侧的受信发布者配置正确Lerna v9 无需额外配置即可自动完成 ID Token 获取、注册表凭证交换并在公开仓库上自动附加 provenance 来源证明——这正是安全发布在现代 monorepo 工具链中的标准姿势。相关实现可进一步阅读 oidc.ts、npm-publish.ts 及其配套测试 oidc.spec.ts。【免费下载链接】lernaLerna is a fast, modern build system for managing and publishing multiple JavaScript/TypeScript packages from the same repository.项目地址: https://gitcode.com/gh_mirrors/le/lerna创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表