18 KiB
v0.1 Secret 与 provider credential 分发规格
本文定义 AgentRun v0.1 的 Secret 和 Code Agent provider credential 分发边界。真实 Code Agent backend 需要上游模型凭据;Codex stdio profile 测试凭据以 ~/.codex/auth.json、~/.codex/config.toml 和必要的 profile-local model catalog 形态为输入源,通过 Kubernetes Secret 投影进入 runner/backend Pod。这些值不得进入 Git source、GitOps branch、artifact catalog、event、trace、日志或 CLI 输出。
在装配 SPEC 中,本文承担 SecretRef、projection、rotation 和 redaction 规则;运行时 credential 必须先归入 ProfileRef、ResourceBundleRef.credentialRef 或 executionPolicy.secretScope.toolCredentials[],再由 runner Job 装配。权威装配模型见 spec-v01-runtime-assembly.md。
设计目标
- API Key、Codex auth/config 等 provider credential 只通过 Kubernetes SecretRef 分发到需要它的 manager、runner 或 backend adapter。
deploy/deploy.json只记录 SecretRef 名称、key 名称、mount/env intent 和 secret scope,不记录 Secret 值。v0.1-gitops的 rendered manifests 只能引用 Secret 名称和 key,不包含 Secret data。agentrun-mgr保存 run 的executionPolicy.secretScope,但保存的是 credential source reference,不是 credential value。- runner 和 backend adapter 只能消费 manager 已授权的 secret scope,不能枚举 namespace 内所有 Secret。
Secret 分类
| Secret 类别 | 用途 | 默认消费者 | v0.1 规则 |
|---|---|---|---|
| Postgres DSN | manager 连接 durable store | agentrun-mgr |
只通过 agentrun-v01-mgr-db/DATABASE_URL 注入。 |
| Codex stdio profile 凭据文件 | 真实 Code Agent backend 调上游模型 | runner 或 backend adapter | codex、deepseek 与 minimax-m3 使用 auth.json/config.toml 文件形态;dsflash-go 额外要求 model-catalog.json。这些文件只通过 profile-scoped Kubernetes SecretRef 文件投影注入,不写入 run payload。 |
| Git SSH deploy key | Tekton checkout source/GitOps promotion,Argo 读取 GitOps branch | Tekton、Argo CD | 只存在于 agentrun-ci 或 argocd Secret;不进入 runtime Pod。 |
| Registry credential | push/pull private registry | Tekton、runtime imagePullSecret | 只作为 ServiceAccount/imagePullSecret 引用。 |
| Tool credential | GitHub PR、issue、UniDesk SSH passthrough、artifact registry 等 agent shell/tool 授权 | runner/backend adapter | 必须通过 executionPolicy.secretScope.toolCredentials[] 的 SecretRef 装配进入运行时;不是 Queue integration,也不能用 transientEnv 承载长期 credential。 |
| Future tenant credential | tenant 专属工具或外部服务 | runner/backend adapter | 必须先扩展装配 SPEC 的 SecretRef 和 secret scope,再允许 run 引用。 |
固定命名建议
| 对象 | v0.1 建议 |
|---|---|
| Manager DB Secret | agentrun-v01-mgr-db key DATABASE_URL |
| Codex Provider Secret | agentrun-v01-provider-codex keys auth.json、config.toml |
| DeepSeek Provider Secret | agentrun-v01-provider-deepseek keys auth.json、config.toml |
| MiniMax-M3 Provider Secret | agentrun-v01-provider-minimax-m3 keys auth.json、config.toml |
| dsflash-go Provider Secret | agentrun-v01-provider-dsflash-go keys auth.json、config.toml、model-catalog.json |
| Provider projection target | 只读 /var/run/agentrun/secrets/<profile>-<index>/auth.json、config.toml 和 profile 需要的额外文件,再复制到当前 run/profile 的 writable CODEX_HOME |
| Provider config | 非敏感 base URL/model 可以来自 config.toml 或 ConfigMap;credential value 不得放入 ConfigMap。 |
| Tekton Git SSH Secret | agentrun-ci/agentrun-git-ssh |
| Argo Git SSH Secret | argocd/agentrun-git-ssh |
| GitHub Tool Secret | agentrun-v01-tool-github-pr key GH_TOKEN |
| UniDesk SSH Tool Secret | agentrun-v01-tool-unidesk-ssh key UNIDESK_SSH_CLIENT_TOKEN |
| Runtime ServiceAccount | agentrun-v01-mgr、agentrun-v01-runner |
命名可以在实现时因集群约束调整,但必须满足 lane 独立、用途单一、最小 RBAC 和不跨 v0.1/v0.2 复用的原则。
Codex 测试凭据注入
v0.1 综合联调使用的 Codex stdio profile 测试凭据源固定为 operator 环境中的文件形态:
~/.codex/auth.json
~/.codex/config.toml
这两个文件只能作为 Kubernetes Secret 创建或轮换的输入源。codex profile 默认使用 operator 当前 Codex 配置;deepseek profile 使用 operator 准备的 DeepSeek-compatible Codex 配置,可以来自另一个 --codex-home 或显式 --auth-file/--config-file;minimax-m3 profile 使用从 HWLAB Code Queue 现有 MiniMax API key 派生的 Codex 配置,模型固定为 MiniMax-M3,wire API 使用当前 Codex app-server 支持的 responses;dsflash-go 使用 deepseek-v4-flash、1M/900k context 和 model-catalog.json。禁止把宿主机 ~/.codex 以 hostPath 挂入 runner/backend Pod,禁止复制进镜像,禁止提交到 source branch、GitOps branch、artifact catalog、issue、PR、event、trace、日志或 CLI 输出。
默认 Secret projection 规则:
| 项目 | v0.1 规格 |
|---|---|
| Kubernetes Secret | agentrun-v01/agentrun-v01-provider-codex、agentrun-v01/agentrun-v01-provider-deepseek、agentrun-v01/agentrun-v01-provider-minimax-m3 或 agentrun-v01/agentrun-v01-provider-dsflash-go |
| Secret key | auth.json,来自 ~/.codex/auth.json |
| Secret key | config.toml,来自 ~/.codex/config.toml |
| Secret key | model-catalog.json,仅 dsflash-go 必需,必须与 config.toml 的 model_catalog_json 指向同一 runtime 路径。 |
| Projection path | 只读 Secret projection 挂到 /var/run/agentrun/secrets/<profile>-<index>/auth.json、config.toml 和 profile 需要的额外文件;该路径只作为 credential source。 |
| Runtime config path | runner 启动时把当前 backendProfile 授权的 Secret projection 复制到 writable CODEX_HOME,Kubernetes Job 默认使用该 Job 独占的 /home/agentrun/.codex-<profile>/auth.json、config.toml 和 profile 需要的额外文件;复用进程必须使用 run/profile 独占目录。 |
| Projection mode | 只读,建议 0400 或等价最小权限 |
| Runtime env | HOME=/home/agentrun,CODEX_HOME=/home/agentrun/.codex-<profile>,AGENTRUN_CODEX_SECRET_HOME=<projection path>;不得 fallback 到节点宿主机 home。 |
Secret 创建和轮换必须通过 Kubernetes 密钥管理完成。deploy/deploy.json 只写 SecretRef 名称、key 和 mount intent;v0.1-gitops rendered manifests 只引用 Secret,不包含 Secret data。
Provider API Key 的 Web 配置由 spec-v01-provider-profile-management.md 定义:HWLAB Cloud API 鉴权后委托 AgentRun manager 更新受控 profile Secret/config。该路径仍只写 Kubernetes Secret data,不把 API Key 写入 Git、GitOps、Postgres、event、trace、日志或 CLI 输出。
Run secretScope 合同
Run 的 executionPolicy.secretScope 只能包含引用,不包含值。provider credential 使用 providerCredentials[];GitHub PR、UniDesk SSH passthrough 等 agent shell/tool 授权使用装配 SPEC 定义的 toolCredentials[],不得混入 transientEnv。示例形态:
{
"providerCredentials": [
{
"profile": "codex",
"secretRef": {
"namespace": "agentrun-v01",
"name": "agentrun-v01-provider-codex",
"keys": ["auth.json", "config.toml"],
"mountPath": "~/.codex"
}
},
{
"profile": "deepseek",
"secretRef": {
"namespace": "agentrun-v01",
"name": "agentrun-v01-provider-deepseek",
"keys": ["auth.json", "config.toml"],
"mountPath": "~/.codex"
}
},
{
"profile": "minimax-m3",
"secretRef": {
"namespace": "agentrun-v01",
"name": "agentrun-v01-provider-minimax-m3",
"keys": ["auth.json", "config.toml"],
"mountPath": "~/.codex"
}
},
{
"profile": "dsflash-go",
"secretRef": {
"namespace": "agentrun-v01",
"name": "agentrun-v01-provider-dsflash-go",
"keys": ["auth.json", "config.toml", "model-catalog.json"],
"mountPath": "~/.codex"
}
}
],
"allowCredentialEcho": false
}
规则:
allowCredentialEcho必须固定为false。secretRef.namespace默认只能是 run 所在 lane namespace 或明确批准的 platform namespace。- manager 可以保存
secretRef,但不得读取 Secret 值后存库。 - runner/backend adapter 获得 Secret 的方式必须来自 Kubernetes env/file projection 或受限 Secret API 读取;Codex 默认从只读 Secret projection 复制
auth.json、config.toml和 profile 需要的额外文件到 writableCODEX_HOME后启动 app-server,不得通过 run payload、event、CLI 参数或日志传递。 - runner/backend adapter 只能选择与 run
backendProfile同名的 provider credential;backendProfile=deepseek、backendProfile=minimax-m3或backendProfile=dsflash-go缺少 matching SecretRef 时必须secret-unavailable,不得 fallback 到codex或另一个 profile。 - manager 会按内建 profile 的
requiredSecretKeys规范化secretRef.keys;消费侧旧 payload 即使只提交auth.json/config.toml,dsflash-gorunner Job 也必须投影model-catalog.json。若实际 Kubernetes Secret 缺少该 key,run 必须在装配或 readiness 阶段失败为结构化secret-unavailable。 - Secret projection 不能直接作为
CODEX_HOME。Codex app-server 会读取并可能维护默认配置、PATH 或运行态文件;把只读 Secret volume 直接挂到CODEX_HOME会造成启动期写入失败。v0.1 的固定边界是:Secret volume 只读、/home/agentrun由emptyDir提供可写 runtime home、复制动作只发生在 runner/backend 容器内且不打印文件内容。 - SecretRef 不存在或 RBAC 不允许时,run 必须失败为结构化
failureKind=secret-unavailable或等价错误,不得降级成无凭证重试风暴。 toolCredentials的 SecretRef/projection/redaction 规则以 spec-v01-runtime-assembly.md 为准;本文只约束 Secret value 不落库、不输出、不进入 Git source 或 GitOps Secret data。
runner-job transientEnv
transientEnv 用于承接调度方生成的短期、单次 runner Job 运行上下文,例如 HWLAB Code Agent 的 owner-scoped HWPOD/runtime API key、runtime URL 和非敏感 UniDesk frontend 地址。它不是 provider credential、tool credential,也不是 run durable fact。
规则:
transientEnv只能出现在POST /api/v1/runs/:runId/runner-jobs请求中;不得写入CreateRunInput、command payload、event payload 或 result envelope 的 value 明文。- manager 不对
transientEnv条目数量设固定上限,只校验数组形态、env name 合法且唯一、value 非空和单值长度;runner job payload hash 只纳入 env name 与 value hash。 - response、runner job status、event 和 dry-run manifest 只能展示 env name、count 和
valuesPrinted=false;dry-run manifest 中的 transient env value 必须显示为REDACTED。 - 正式 Kubernetes Job manifest 会把 value 注入到本次 runner container env;该 token 必须由调度方控制 TTL、权限和业务授权范围。
- AgentRun 不解释 HWLAB HWPOD 权限,也不把业务鉴权做成通用 policy;AgentRun 只负责不持久化、不回显、不扩散这类短期 env value。
- GitHub token、UniDesk SSH client token、SSH private key、provider API key、registry token 等 provider/tool 可复用 credential 不得通过
transientEnv注入;必须先进入装配 SPEC 的 SecretRef 路径。HWLAB dispatcher 生成并限定 owner/HWPOD/runtime scope 的HWLAB_API_KEY属于业务运行上下文,可以作为单次 runner Job env 透传,但不得变成 AgentRun durable fact 或通用授权。
分发路径
v0.1 默认路径:
deploy/deploy.json
-> declares SecretRef names and mount/env intent only
Tekton promotion
-> renders SecretRef references into v0.1-gitops manifests
Argo CD
-> syncs workload references to agentrun-v01
Kubernetes Secret
-> created from profile-specific auth.json, config.toml and required extra files by operator or approved secret-management flow
runner/backend Pod
-> receives Codex auth/config/model catalog via read-only file projection
-> copies authorized files into writable CODEX_HOME before starting Codex app-server
Secret 创建和轮换不由 source branch 自动生成;source branch 只声明需要哪个 SecretRef。后续如果接入 External Secrets、Vault、SealedSecrets 或 SOPS,必须新增或更新本 spec,明确 controller、source of truth、rotation 和 redaction 规则。
Codex Secret dry-run 工具
v0.1 提供只读 CLI 工具,用 operator 本地 ~/.codex/auth.json、~/.codex/config.toml 和 profile 需要的额外文件构造 Kubernetes Secret 创建计划:
./scripts/agentrun secrets codex render --dry-run [--profile codex|deepseek|minimax-m3|dsflash-go]
可选参数:
--codex-home <dir>:覆盖默认~/.codex输入目录。--profile <name>:默认codex;deepseek、minimax-m3和dsflash-go使用同一文件形态但默认 Secret name 分别为对应agentrun-v01-provider-<profile>。--auth-file <path>/--config-file <path>:分别覆盖输入文件路径。--model-catalog-file <path>:覆盖dsflash-go的model-catalog.json输入文件路径。--namespace <name>:默认agentrun-v01。--secret-name <name>:默认随 profile 变化,codex为agentrun-v01-provider-codex,deepseek为agentrun-v01-provider-deepseek,minimax-m3为agentrun-v01-provider-minimax-m3。
输出必须是 JSON,并且只包含 namespace、secretName、keys、每个输入文件的 bytes、sha256/contentHash、整体 hash、redaction 状态、apply 命令形状和 Secret manifest 摘要。输出不得包含 Secret value、auth.json 明文、config.toml 明文、model-catalog.json 明文、base64 data 字段或可直接恢复 credential 的内容。工具只支持 --dry-run;不得执行 kubectl apply。
失败必须结构化返回 failureKind:缺文件、不可读文件或空 credential 归类为 secret-unavailable;非法 JSON/TOML 归类为 schema-invalid。
日志与事件 Redaction
- event、trace、日志、CLI 输出、health 和 diagnostics 不得打印 Secret 值。
Authorization、api_key、token、password、URL credential、DSN password、Codexauth.json和config.toml文件内容必须 redacted。- 可以打印 SecretRef 名称、key 名称、credential source、是否存在、是否被挂载、是否通过 readiness 检查。
- provider auth 失败只能报告 failure kind、HTTP status 分类和 request id;不得打印请求 header 或 body 中的凭据。
测试规格
T1 SecretRef render
阅读本文和 spec-v01-cicd.md,然后检查 deploy/deploy.json 只包含 SecretRef 名称/key 和 mount/env intent;rendered GitOps manifest 也只包含 SecretRef,不包含 Secret data。
T2 Runner credential projection
阅读本文,然后分别启动 backendProfile=codex、backendProfile=deepseek、backendProfile=minimax-m3 与 backendProfile=dsflash-go 的最小 backend runner dry-run,确认 Pod file projection 挂在 /var/run/agentrun/secrets/... 且只读,/home/agentrun 是 writable runtime home,runner/backend 只把当前 profile 授权文件复制到 CODEX_HOME 后再启动 Codex;dsflash-go 必须同时投影并复制 model-catalog.json;event、日志和 CLI 输出只显示 redacted credential source,不显示文件内容。
T3 Missing secret failure
阅读本文,然后用一个不存在的 provider SecretRef 创建 run,确认 run 失败为结构化 secret-unavailable,不会打印 Secret 值,也不会无限重试。
规格的实现情况
| 规格项 | 状态 | 说明 |
|---|---|---|
| Secret 分发规格 | 已定义 | 本文为 v0.1 provider credential 分发权威。 |
| Kubernetes SecretRef 注入 | 已实现/已通过主闭环 | runner Job dry-run 和正式 Job 创建路径已按 run executionPolicy.secretScope.providerCredentials 生成 Secret volume projection、writable runtime home 和 AGENTRUN_CODEX_SECRET_HOME;真实 Secret 与 Codex turn 已通过主闭环。 |
| Codex Secret dry-run 工具 | 已实现 | ./scripts/agentrun secrets codex render --dry-run 只输出 Secret 创建计划、hash 和 redacted manifest 摘要,不执行 apply。 |
| Codex auth/config file projection | 已实现主路径 | backend readiness 检查 auth.json/config.toml 可读性,缺失时返回 secret-unavailable;真实 runner Job 将只读 projection 复制到 writable CODEX_HOME。 |
| DeepSeek profile SecretRef | 已实现/已通过主闭环 | 已新增 agentrun-v01-provider-deepseek render、GitOps/RBAC 引用、Job projection、profile 选择和负向 missing-secret 自测试;真实 Secret 创建与 Kubernetes Job projection 已通过主闭环,轮换仍由 Kubernetes 密钥管理流程完成。 |
| MiniMax-M3 profile SecretRef | 已实现/待真实主闭环 | 已新增 agentrun-v01-provider-minimax-m3 render、GitOps/RBAC 引用、Job projection、profile 选择和负向 missing-secret 自测试;真实 Secret 创建使用 HWLAB Code Queue 现有 MiniMax API key,轮换仍由 Kubernetes 密钥管理流程完成。 |
| dsflash-go profile SecretRef | 已实现/待真实主闭环 | 已新增 agentrun-v01-provider-dsflash-go 的 model-catalog.json required key、Secret render、Job projection、writable CODEX_HOME 复制和负向 readiness;真实 profile turn 仍需按 provider 管理 canary 和 HWLAB 原入口复测。 |
| Tool credential SecretRef | 已实现最小 env projection | executionPolicy.secretScope.toolCredentials[] 已支持 tool=github、tool=unidesk-ssh 与 projection.kind=env,runner Job 通过 Kubernetes secretKeyRef 注入 env;CLI、event、runner job response 和 dry-run 只显示 SecretRef/projection 元数据,不输出值。 |
| redaction 最小规则 | 已实现主路径 | Secret dry-run 工具、event、Job dry-run 输出、self-test 和真实主闭环均不打印 Secret value;复杂审计按 spec-v01-validation.md 人工抽查。 |
| 外部 secret manager | 未采用 | 如需 Vault/ExternalSecrets/SOPS,后续单独更新规格。 |