- 将 terraform init -backend-config 中的 endpoints={s3="..."} HCL map
语法改为 endpoints.s3=... 点号语法(前者在 -backend-config flag 中无效,
导致 R2 endpoint 未被传递,Terraform 回退 AWS 默认 endpoint 签名失败)
- 补全 workflow 顶部 TLDR 前置条件注释(6 项)
- 新增 docs/operations/iac-prerequisites.md(前置条件完整指南含 R2 搭建)
- vault-github-actions.md 补充 §7 交叉引用
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
4.7 KiB
Vault + GitHub Actions 配置(xworkspace-console)
xworkspace-console 的 GitHub Actions 经 HashiCorp Vault (https://vault.svc.plus)
OIDC 登录、从共享 CICD KV 读取密钥。只记录流程、路径、字段名与原则,
不含任何敏感值。延续既有统一模式(见 vault-github-actions-2026-06-06.md
与 vault-github-actions-ssh-deploy-runbook.md)。
1. 全局前提(已存在)
jwtauth mount:Typejwt、Pathjwt/、Accessor 如auth_jwt_6fd8b418oidc_discovery_url = https://token.actions.githubusercontent.combound_issuer = https://token.actions.githubusercontent.com
- 共享机密 KV(KV v2):UI
secrets/kv/kv/CICD,API 读路径kv/data/CICD
2. role + policy
role/policy 命名 github-actions-xworkspace-console,读共享 kv/data/CICD。
# 2.1 policy:允许读共享 CICD KV 路径
vault policy write github-actions-xworkspace-console - <<'EOF'
path "kv/data/CICD" {
capabilities = ["read"]
}
path "kv/metadata/CICD" {
capabilities = ["read", "list"]
}
# LLM provider keys 在 openclaw 路径
path "kv/data/openclaw" {
capabilities = ["read"]
}
path "kv/metadata/openclaw" {
capabilities = ["read", "list"]
}
EOF
# 2.2 role:仅绑定本仓库的 GitHub OIDC 身份
vault write auth/jwt/role/github-actions-xworkspace-console \
role_type="jwt" \
user_claim="repository" \
bound_audiences="vault" \
bound_claims_type="glob" \
bound_claims='{"repository":"ai-workspace-lab/xworkspace-console","sub":"repo:ai-workspace-lab/xworkspace-console:*"}' \
token_policies="github-actions-xworkspace-console" \
token_ttl="20m" token_max_ttl="30m"
权限模型一致:
repository = ai-workspace-lab/xworkspace-console、sub = repo:ai-workspace-lab/xworkspace-console:*、bound_audiences=["vault"]。 共享 KV 仅授予 read。如需仅限分支,把sub收窄为repo:ai-workspace-lab/xworkspace-console:ref:refs/heads/main。
3. KV 字段(复用既有共享键,跨两条路径)
| Vault 路径 | 键 | 映射到输出 | 用途 |
|---|---|---|---|
kv/data/CICD |
VULTR_API_KEY |
VULTR_API_KEY |
provision:TF_VAR_vultr_api_key |
kv/data/CICD |
CLOUDFLARE_DNS_API_TOKEN |
CLOUDFLARE_DNS_API_TOKEN |
dns:Cloudflare DNS 编辑 |
kv/data/CICD |
SSH_PRIVATE_DEPLOY_KEY_B64 |
ANSIBLE_SSH_KEY_B64 |
连主机 SSH 私钥(优先,单行 base64) |
kv/data/CICD |
SSH_PRIVATE_DEPLOY_KEY |
ANSIBLE_SSH_KEY |
同上原始多行(回退) |
kv/data/openclaw |
DEEPSEEK_API_KEY / NVIDIA_API_KEY / OLLAMA_API_KEY |
同名 | deploy:注入主机的 LLM provider keys |
kv/data/CICD |
TF_STATE_ENDPOINT/BUCKET/ACCESS_KEY/SECRET_KEY/REGION |
同名 | 可选远端 TF state(不配则本地 state) |
所有键均已存在(LLM key 在
kv/openclaw,其余共享键在kv/CICD)。 vault-action 一个步骤可跨多路径读,每行自带路径。
主机登录用
SSH_PRIVATE_DEPLOY_KEY,其公钥SSH_PUBLIC_DEPLOY_KEY须写入ai-workspace-infra的vultr-vps/config/resources/ai-workspace-hosts.yaml的ssh_keys[].public,否则 runner 连不上新建主机。
4. workflow 接入(已落地)
.github/workflows/deploy-ai-workspace-iac.yaml:
permissions.id-token: write(+contents: read)- 每 job 用
hashicorp/vault-action@v2:method: jwt、role: github-actions-xworkspace-console、jwtGithubAudience: vault,从kv/data/CICD读所需键(用KV键 | 输出名映射;可选键配ignoreNotFound) - 步骤用
steps.vault.outputs.<输出名>,不再用 GitHub Actions Secrets - SSH 落盘优先解码
ANSIBLE_SSH_KEY_B64(=SSH_PRIVATE_DEPLOY_KEY_B64)、回退原始, 写~/.ssh/id_deploy并ssh-keygen -y -f自检 - 远端 TF state 开关由
steps.vault.outputs.TF_STATE_BUCKET是否非空决定
5. 验收
- 触发
Deploy AI Workspace (IaC + Ansible + Cloudflare)。 - 每个 job 的
Load Vault secrets (OIDC)成功(读到共享 CICD KV)。 - provision:
Terraform apply成功、产出cmdb.json矩阵。 - deploy:
Configure SSH(B64 优先)+Run on-host bootstrap成功。 - dns:
Reconcile Cloudflare DNS成功。
6. 故障处理
vault-action报valid path and key:secrets每行;分隔、路径含data/。- role 不匹配 /
permission denied:核对 OIDCrepository/sub与 rolebound_claims,及 policy 是否含kv/data/CICD。 Load key ... error in libcrypto:确认优先解码了SSH_PRIVATE_DEPLOY_KEY_B64。Permission denied (publickey):确认SSH_PUBLIC_DEPLOY_KEY已进 hosts.yaml 并与私钥配对。
7. 参考
- 完整前置条件清单(含 TF state 后端搭建):iac-prerequisites.md