すべてのGitHub Actionsワークフロー実行は、GitHubがホストする発行者(https://token.actions.githubusercontent.com)から署名付きアイデンティティトークンをリクエストできます。Workload Identity Federationを使用すると、ワークフローはそのトークンを短期間有効なAnthropicアクセストークンと交換するため、リポジトリにANTHROPIC_API_KEYシークレットを保存することなく、CIジョブからClaude APIを呼び出すことができます。
トークンのsubクレームには、リポジトリとトリガーのコンテキストがエンコードされています。ブランチへのプッシュの場合、形式はrepo:<owner>/<repo>:ref:refs/heads/<branch>です。プルリクエストの実行では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ジョブ内では、ランナーは2つの環境変数を公開します:ACTIONS_ID_TOKEN_REQUEST_URLとACTIONS_ID_TOKEN_REQUEST_TOKENです。リクエストトークンをベアラー認証情報として、選択したオーディエンスをクエリパラメータとしてリクエストURLを呼び出し、返された「JSON Web Token」(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-jwtJavaScriptを使用したい場合は、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"
}sub形式の完全なリストについては、GitHubのOIDCサブジェクトクレームリファレンスを参照してください。
Claude ConsoleでSettings → Workload identityを開き、Connect workloadをクリックして、GitHub Actionsタイルを選択します。ウィザードが発行者の登録、サービスアカウントの作成、フェデレーションルールの作成を案内します。
ウィザードがこれらのリソースを作成します。ウィザードに入力する場合でも、Admin API に送信する場合でも、以下の値を使用してください。
フェデレーション発行者: GitHubはOIDCディスカバリードキュメントとJWKSを公開しているため、ディスカバリーモードを使用します。GitHubがキーをローテーションすると、Anthropicは自動的にキーを更新します。
{
"name": "github-actions",
"issuer_url": "https://token.actions.githubusercontent.com",
"jwks": { "type": "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
}ワークロードが許す限り具体的に指定してください。subの末尾のセグメントはref:...、environment:...、pull_requestイベント間で異なるため、ルールが同じリポジトリからの複数のイベントタイプに一致する必要がある場合にのみ、subject_prefixをrepo:your-org/your-repo:*に緩和してください(claims.ref制約と組み合わせて)。
ジョブにフェデレーション環境変数を設定し、通常どおり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-opus-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello, Claude"}],
)
print(next(block.text for block in message.content if block.type == "text"))GitHubが発行する各アイデンティティトークンは、発行後約5分で有効期限が切れます。トークンリクエストエンドポイント(ACTIONS_ID_TOKEN_REQUEST_URL)はジョブ全体で有効なため、いつでも新しいトークンを取得できます。SDKは最初の使用時にトークンを交換し、結果として得られるAnthropicアクセストークンをキャッシュします。Anthropicトークンの有効期間より長く実行されるジョブの場合、SDKは更新のたびにANTHROPIC_IDENTITY_TOKEN_FILEを再読み取りするため、取得ステップを定期的に再実行(またはバックグラウンドループでラップ)してファイルを最新の状態に保ってください。あるいは、ファイルパスを使用する代わりに、ACTIONS_ID_TOKEN_REQUEST_URLを直接呼び出すトークンプロバイダーコールバックをSDKに渡すこともできます。
交換が成功すると、sk-ant-oat01-で始まるaccess_tokenと、秒単位のexpires_in値が返されます。400 invalid_grantの場合は、失敗した交換のトラブルシューティングを参照してください。GitHub Actions側で最も一般的な原因は、subクレームの形式が一致しないことです(末尾のセグメントはref:...、environment:...、pull_requestイベント間で異なります)。
repo:your-org/*というsubject_prefixだけでは、組織内のすべてのリポジトリに一致し、ref制約がない場合はフォークからトリガーされたpull_request実行にも一致します。一致するリポジトリに対してプルリクエストを開くことができる人は誰でも、フェデレーションされたAnthropicトークンを取得できる可能性があります。
ルールのmatchブロックを、ユースケースに適合する最も狭いスコープにロックしてください:
subject_prefix: "repo:your-org/your-repo:*"を使用して、組織内の他のリポジトリが一致しないようにします。claimsの下に"ref": "refs/heads/main"(またはリリースブランチ)を追加して、プルリクエスト実行やフィーチャーブランチが一致しないようにします。subの解析のエッジケースに対する多層防御チェックとして、claimsの下に"repository_owner": "your-org"を追加します。subject_prefix: "repo:your-org/your-repo:environment:production"に一致させ、GitHubで必須レビュアーを設定してその環境をゲートします。Was this page helpful?