在 CI/CD 中维护 Codex 账号认证(高级)

在 CI/CD 中维护 Codex 账号认证(高级)

介绍如何在可信的 CI/CD 运行器上安全保存并回写 Codex 的 auth.json,利用内建刷新机制维护 ChatGPT 托管认证,并处理自托管与临时运行器、密钥存储、并发隔离和认证失效后的重新登录。

在 CI/CD 中维护 Codex 账号认证(高级)#

Codex 中文站说明: 本页围绕“在 CI/CD 中维护 Codex 账号认证(高级)”重新补充了中文使用场景和验证重点。界面名称可能随 Codex 版本更新,请以当前客户端为准。

使用 Codex 内置的刷新流程,让 auth.json 在受信任的 CI/CD runner 中持续可用

本指南说明如何在可信的 CI/CD 运行器上维持 ChatGPT 托管的 Codex 认证,而无须自行调用 OAuth token endpoint。

自动化任务应优先使用 API key 认证。只有当工作流确实需要以你的 Codex 账号身份运行时,才使用本指南中的方案。

整体流程如下:

  1. 在可信设备上运行一次 codex login,生成 auth.json
  2. 将该文件放到运行器上。
  3. 正常运行 Codex。
  4. 当会话过期时,由 Codex 自动刷新。
  5. 保存刷新后的 auth.json,供下一次运行使用。

这是一种面向企业及其他可信私有自动化环境的高级工作流。对于大多数 CI/CD 任务,API key 仍是推荐方案。

请像保护密码一样保护 ~/.codex/auth.json,因为其中包含访问令牌。不要将它提交到仓库、粘贴到工单或在聊天中分享,也不要在公开仓库或开源仓库中使用这一方案。

工作原理#

Codex 本身已经能够刷新由 ChatGPT 托管的会话。

以当前的开源客户端为准:

  • Codex 会从 auth.json 加载本地认证缓存。
  • 如果 last_refresh 距今超过约 8 天,Codex 会先刷新令牌集,再继续运行。
  • 刷新成功后,Codex 会把新令牌和新的 last_refresh 写回 auth.json
  • 如果请求收到 401,Codex 也有内建的刷新并重试流程。

因此,受支持的 CI/CD 策略不是“自行调用刷新 API”,而是“运行 Codex,并持久化更新后的 auth.json”。

适用条件#

只有同时满足以下条件时,才使用本指南:

  • 你需要 ChatGPT 托管的 Codex 认证,而不是 API key。
  • 远程运行器无法执行 codex login
  • 运行器属于可信的私有基础设施。
  • 你能够在多次运行之间保存刷新后的 auth.json
  • 一份 auth.json 只由一台机器或一组串行执行的任务使用。

本指南适用于 Codex 管理的 ChatGPT 认证(auth_mode: "chatgpt")。

它不适用于:

  • API key 认证。
  • 由宿主应用管理外部 token 的集成(auth_mode: "chatgptAuthTokens")。
  • Codex 之外的通用 OAuth 客户端。

如果凭据保存在操作系统钥匙串中,请先改用文件存储。参见凭据存储

仅初始化一次 auth.json#

在能够通过浏览器登录的可信设备上执行以下步骤:

  1. 配置 Codex,将凭据保存到文件中:
toml
cli_auth_credentials_store = "file"
  1. 运行:
bash
codex login
  1. 验证该文件是否为 ChatGPT 托管认证:
bash
AUTH_FILE="${CODEX_HOME:-$HOME/.codex}/auth.json"

jq '{
auth_mode,
has_tokens: (.tokens != null),
has_refresh_token: ((.tokens.refresh_token // "") != ""),
last_refresh
}' "$AUTH_FILE"

只有满足以下条件时才继续:

  • auth_mode"chatgpt"
  • has_refresh_tokentrue

然后,将 auth.json 的内容存入 CI/CD 密钥管理系统,或把文件复制到可信且可持久化的运行器。

推荐方案:使用自托管运行器的 GitHub Actions#

最简单的全自动方案,是使用带持久化 CODEX_HOME 的自托管 GitHub Actions 运行器。

这一方案具有以下优势:

  • 运行器可以在多次任务之间保留磁盘上的 auth.json
  • Codex 可以直接刷新原文件。
  • 后续任务会自动使用刷新后的令牌。
  • 原始 secret 只在初始化或重新写入凭据时需要。

关键在于:仅当 auth.json 不存在时才写入初始文件。如果每次运行都用原始 secret 覆盖该文件,就会丢掉 Codex 上一次写入的刷新结果。

下面是一份定时工作流示例:

yaml
name: Keep Codex auth fresh

on:
schedule:
- cron: "0 9 * * 1"
workflow_dispatch:

jobs:
keep-codex-auth-fresh:
runs-on: self-hosted
steps:
- name: Bootstrap auth.json if needed
shell: bash
env:
CODEX_AUTH_JSON: ${{ secrets.CODEX_AUTH_JSON }}
run: |
export CODEX_HOME="${CODEX_HOME:-$HOME/.codex}"
mkdir -p "$CODEX_HOME"
chmod 700 "$CODEX_HOME"

if [ ! -f "$CODEX_HOME/auth.json" ]; then
printf '%s' "$CODEX_AUTH_JSON" > "$CODEX_HOME/auth.json"
chmod 600 "$CODEX_HOME/auth.json"
fi

- name: Run Codex
shell: bash
run: |
codex exec --json "Reply with the single word OK." >/dev/null

该工作流会:

  • 在首次运行时写入 auth.json
  • 在后续运行中复用同一文件。
  • 当缓存会话达到过期条件时,在正常的 codex exec 步骤中由 Codex 自动刷新。
  • 将刷新后的文件保留在磁盘上,供下一次工作流运行使用。

当前开源客户端会在大约 8 天后把会话视为已过期,因此每周运行一次通常就足够。

临时运行器:恢复文件、运行 Codex,再持久化更新后的文件#

如果使用 GitHub 托管运行器、GitLab 共享运行器或其他临时环境,每个任务结束后,运行器的文件系统都会被清除。此时需要完成一次完整的往返流程:

  1. 从安全存储中恢复当前的 auth.json
  2. 运行 Codex。
  3. 将更新后的 auth.json 写回安全存储。

GitHub Actions 的通用结构如下:

yaml
name: Run Codex with managed auth

on:
workflow_dispatch:

jobs:
codex-job:
runs-on: ubuntu-latest
steps:
- name: Restore auth.json
shell: bash
run: |
export CODEX_HOME="${CODEX_HOME:-$HOME/.codex}"
mkdir -p "$CODEX_HOME"
chmod 700 "$CODEX_HOME"

# Replace this with your secret manager or secure storage command.
my-secret-cli read codex-auth-json > "$CODEX_HOME/auth.json"
chmod 600 "$CODEX_HOME/auth.json"

- name: Run Codex
shell: bash
run: |
codex exec --json "summarize the failing tests"

- name: Persist refreshed auth.json
if: always()
shell: bash
run: |
# Replace this with your secret manager or secure storage command.
my-secret-cli write codex-auth-json < "$CODEX_HOME/auth.json"

关键要求是:回写步骤必须保存 Codex 在本次运行中生成的刷新后文件,而不是最初用于初始化的原始文件。

不需要单独的刷新命令#

任何一次正常的 Codex 运行都可以刷新会话。

因此有两种合适的做法:

  • 让现有的 CI/CD Codex 任务自然刷新该文件。
  • 如果实际任务运行得不够频繁,可以增加一个轻量的定时维护任务,如上面的 GitHub Actions 示例。

会话达到过期条件后,第一次运行 Codex 时就会刷新 auth.json

关键运行规则#

  • 每台运行器或每组串行工作流使用一份独立的 auth.json
  • 不要让并发任务或多台机器共享同一文件。
  • 不要在每次运行时用原始文件覆盖持久化运行器上已经刷新的文件。
  • 不要把 auth.json 存入仓库、日志或公开的产物存储。
  • 如果内建刷新不再有效,请在可信设备上重新生成认证文件。

刷新失效时的处理方法#

该流程可以减少人工操作,但不能保证同一会话永久有效。

出现以下情况时,请用新的 auth.json 重新初始化运行器:

  • Codex 开始返回 401,并且运行器无法继续刷新。
  • refresh token 已被撤销或过期。
  • 另一台机器或并发任务率先轮换了令牌。
  • 安全存储的往返流程失败,恢复了旧文件。

重新初始化:

  1. 在可信设备上运行 codex login
  2. 替换 CI/CD 中保存的 auth.json
  3. 让下一个运行器任务继续使用 Codex 的内建刷新流程。

验证运行器是否持续维护会话#

检查运行器是否仍保存着托管认证所需的令牌,以及 last_refresh 是否存在:

bash
AUTH_FILE="${CODEX_HOME:-$HOME/.codex}/auth.json"

jq '{
auth_mode,
last_refresh,
has_access_token: ((.tokens.access_token // "") != ""),
has_id_token: ((.tokens.id_token // "") != ""),
has_refresh_token: ((.tokens.refresh_token // "") != "")
}' "$AUTH_FILE"

对于持久化运行器,同一文件应在多次运行之间始终存在。对于临时运行器,请确认回写步骤保存的是上一次任务生成的更新后文件。

源码参考#

如需在开源客户端中验证上述行为:

本站实践建议#

落地“在 CI/CD 中维护 Codex 账号认证(高级)”前,建议先在小范围工作区验证身份、权限和审计策略,再逐步推广到团队。企业策略应同时记录负责人、变更时间和回滚方式。

Codex API 与国内使用#

在实践“在 CI/CD 中维护 Codex 账号认证(高级)”相关功能时,如需为 Codex 配置 OpenAI-compatible API,可以前往 APIBest 获取 API Key。第三方服务的模型映射、价格、额度和数据处理方式以 APIBest 当前说明为准。