每次 GitHub Actions 工作流程執行時,都可以向 GitHub 託管的發行者 https://token.actions.githubusercontent.com 請求一個已簽署的身分權杖。透過「Workload Identity Federation」(工作負載身分聯合),您的工作流程可以將該權杖交換為短期的 Anthropic 存取權杖,讓您的 CI 作業無需在儲存庫中儲存 ANTHROPIC_API_KEY 密鑰即可呼叫 Claude API。
權杖的 sub 宣告會編碼儲存庫與觸發情境。對於推送至分支的情況,其格式為 repo:<owner>/<repo>:ref:refs/heads/<branch>。Pull request 執行使用 repo:<owner>/<repo>:pull_request,而受環境管控的部署則使用 repo:<owner>/<repo>:environment:<name>。您的聯合規則會比對此宣告(以及其他宣告,例如 repository_owner 和 ref),以決定哪些工作流程執行可以進行驗證。
id-token: write 權限的 GitHub 儲存庫。GitHub 只會向明確請求的作業發行身分權杖。請在工作流程或作業層級新增 id-token: write 權限:
permissions:
id-token: write
contents: read在作業內部,執行器會公開兩個環境變數:ACTIONS_ID_TOKEN_REQUEST_URL 和 ACTIONS_ID_TOKEN_REQUEST_TOKEN。使用請求權杖作為 bearer 憑證呼叫請求 URL,並將您選擇的 audience 作為查詢參數,然後將回傳的「JSON Web Token」(JSON 網頁權杖),即 JWT,寫入檔案:
- name: Fetch GitHub OIDC token
run: |
curl -sS -H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
"$ACTIONS_ID_TOKEN_REQUEST_URL&audience=https://api.anthropic.com" \
| jq -r .value > /tmp/gha-jwt如果您偏好使用 JavaScript,actions/github-script 透過 core.getIDToken(audience) 提供相同的功能:
- name: Fetch GitHub OIDC token
uses: actions/github-script@v8
with:
script: |
const fs = require('fs');
const token = await core.getIDToken('https://api.anthropic.com');
fs.writeFileSync('/tmp/gha-jwt', token);解碼後的權杖包含描述工作流程執行的宣告。您的聯合規則會比對這些宣告:
{
"iss": "https://token.actions.githubusercontent.com",
"sub": "repo:your-org/your-repo:ref:refs/heads/main",
"aud": "https://api.anthropic.com",
"repository": "your-org/your-repo",
"repository_owner": "your-org",
"ref": "refs/heads/main",
"sha": "abc123...",
"workflow": "CI",
"actor": "octocat",
"event_name": "push"
}請參閱 GitHub 的 OIDC subject 宣告參考文件以取得完整的 sub 格式清單。
依照設定逐步說明,在 Claude Console 中註冊聯合發行者、建立 Anthropic 服務帳戶,並建立聯合規則。請使用以下 GitHub Actions 專屬的值。
聯合發行者: GitHub 公開發布其 OIDC 探索文件與 JWKS,因此請使用探索模式。當 GitHub 輪替金鑰時,Anthropic 會自動重新整理金鑰。
{
"name": "github-actions",
"issuer_url": "https://token.actions.githubusercontent.com",
"jwks_source": "discovery"
}聯合規則: 僅比對您打算信任的工作流程執行。請參閱限制哪些工作流程可以進行驗證,了解如何安全地限定這些宣告的範圍。
{
"name": "gha-main",
"issuer_id": "fdis_...",
"match": {
"subject_prefix": "repo:your-org/your-repo:ref:refs/heads/main",
"audience": "https://api.anthropic.com",
"claims": {
"repository_owner": "your-org"
}
},
"target": {
"type": "service_account",
"service_account_id": "svac_..."
},
"workspace_id": "wrkspc_...",
"oauth_scope": "workspace:developer",
"token_lifetime_seconds": 600
}請盡可能依工作負載所允許的範圍具體設定。只有當規則必須比對來自同一儲存庫的多種事件類型時,才將 subject_prefix 放寬為 repo:your-org/your-repo:*(並搭配 claims.ref 限制),因為 sub 的尾端區段在 ref:...、environment:... 和 pull_request 事件之間會有所不同。
在作業上設定聯合環境變數,並正常呼叫 SDK。Anthropic() 會讀取 ANTHROPIC_IDENTITY_TOKEN_FILE,在第一次請求時交換 JWT,並在存取權杖過期前自動重新整理。
import anthropic
# 從作業環境讀取 ANTHROPIC_FEDERATION_RULE_ID、ANTHROPIC_ORGANIZATION_ID、
# ANTHROPIC_SERVICE_ACCOUNT_ID、ANTHROPIC_WORKSPACE_ID 以及 ANTHROPIC_IDENTITY_TOKEN_FILE
# 等環境變數。
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello, Claude"}],
)
print(message.content[0].text)每個 GitHub 發行的身分權杖在發行後約五分鐘過期。權杖請求端點(ACTIONS_ID_TOKEN_REQUEST_URL)在整個作業期間都保持有效,因此您可以隨時取得新的權杖。SDK 會在首次使用時交換權杖,並快取產生的 Anthropic 存取權杖。對於執行時間超過 Anthropic 權杖有效期的作業,SDK 會在每次重新整理時重新讀取 ANTHROPIC_IDENTITY_TOKEN_FILE,因此請定期重新執行取得步驟(或將其包裝在背景迴圈中)以保持檔案為最新狀態。或者,您也可以傳遞一個權杖提供者回呼給 SDK,直接呼叫 ACTIONS_ID_TOKEN_REQUEST_URL,而不使用檔案路徑。
成功的交換會回傳一個以 sk-ant-oat01- 開頭的 access_token,以及一個以秒為單位的 expires_in 值。若遇到 400 invalid_grant,請參閱疑難排解失敗的交換;GitHub Actions 端最常見的原因是 sub 宣告格式不符(其尾端區段在 ref:...、environment:... 和 pull_request 事件之間會有所不同)。
單獨使用 repo:your-org/* 作為 subject_prefix 會比對您組織中的每個儲存庫,而且若沒有 ref 限制,它也會比對從 fork 觸發的 pull_request 執行。任何能對符合條件的儲存庫開啟 pull request 的人都可能取得聯合的 Anthropic 權杖。
將規則的 match 區塊鎖定在符合您使用情境的最小範圍:
subject_prefix: "repo:your-org/your-repo:*",讓組織中的其他儲存庫不會符合。claims 下新增 "ref": "refs/heads/main"(或您的發布分支),讓 pull request 執行與功能分支不會符合。claims 下新增 "repository_owner": "your-org",作為防範 sub 解析邊緣情況的縱深防禦檢查。subject_prefix: "repo:your-org/your-repo:environment:production",並在 GitHub 中為該環境設定必要的審核者管控。Was this page helpful?