From 4257c8e0591343e1130ae550a49ae34dd17c7060 Mon Sep 17 00:00:00 2001 From: Ashwin Bhat Date: Fri, 22 May 2026 15:46:06 -0700 Subject: [PATCH] Use workload identity federation for Claude auth in CI workflows (#1344) Switch claude.yml, claude-review.yml, and issue-triage.yml from the anthropic_api_key secret to the workload identity federation inputs. The federation rule, organization, and service account IDs are read from repository variables; issue-triage.yml additionally gains the id-token: write permission required to request the OIDC token. --- .github/workflows/claude-review.yml | 7 ++++++- .github/workflows/claude.yml | 7 ++++++- .github/workflows/issue-triage.yml | 10 +++++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/.github/workflows/claude-review.yml b/.github/workflows/claude-review.yml index db490377..6f4dde5c 100644 --- a/.github/workflows/claude-review.yml +++ b/.github/workflows/claude-review.yml @@ -20,7 +20,12 @@ jobs: - name: PR Review with Progress Tracking uses: anthropics/claude-code-action@v1 with: - anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + # Authenticate to the Claude API via Workload Identity Federation + # (the workflow's OIDC token is exchanged for a short-lived access + # token) instead of a static API key. See docs/setup.md. + anthropic_federation_rule_id: ${{ vars.ANTHROPIC_FEDERATION_RULE_ID }} + anthropic_organization_id: ${{ vars.ANTHROPIC_ORGANIZATION_ID }} + anthropic_service_account_id: ${{ vars.ANTHROPIC_SERVICE_ACCOUNT_ID }} prompt: "/review-pr REPO: ${{ github.repository }} PR_NUMBER: ${{ github.event.pull_request.number }}" claude_args: | diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index 9ce5ed39..89bf701a 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -33,7 +33,12 @@ jobs: id: claude uses: anthropics/claude-code-action@main with: - anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + # Authenticate to the Claude API via Workload Identity Federation + # (the workflow's OIDC token is exchanged for a short-lived access + # token) instead of a static API key. See docs/setup.md. + anthropic_federation_rule_id: ${{ vars.ANTHROPIC_FEDERATION_RULE_ID }} + anthropic_organization_id: ${{ vars.ANTHROPIC_ORGANIZATION_ID }} + anthropic_service_account_id: ${{ vars.ANTHROPIC_SERVICE_ACCOUNT_ID }} claude_args: | --allowedTools "Bash(bun install),Bash(bun test:*),Bash(bun run format),Bash(bun typecheck)" --model "claude-opus-4-7" diff --git a/.github/workflows/issue-triage.yml b/.github/workflows/issue-triage.yml index b713a39f..9163a387 100644 --- a/.github/workflows/issue-triage.yml +++ b/.github/workflows/issue-triage.yml @@ -11,6 +11,9 @@ jobs: permissions: contents: read issues: write + # Required to mint the OIDC token that is exchanged for a Claude API + # access token (Workload Identity Federation). + id-token: write steps: - name: Checkout repository @@ -24,6 +27,11 @@ jobs: CLAUDE_CODE_SCRIPT_CAPS: '{"edit-issue-labels.sh":2}' with: prompt: "/label-issue REPO: ${{ github.repository }} ISSUE_NUMBER: ${{ github.event.issue.number }}" - anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + # Authenticate to the Claude API via Workload Identity Federation + # (the workflow's OIDC token is exchanged for a short-lived access + # token) instead of a static API key. See docs/setup.md. + anthropic_federation_rule_id: ${{ vars.ANTHROPIC_FEDERATION_RULE_ID }} + anthropic_organization_id: ${{ vars.ANTHROPIC_ORGANIZATION_ID }} + anthropic_service_account_id: ${{ vars.ANTHROPIC_SERVICE_ACCOUNT_ID }} allowed_non_write_users: "*" # Required for issue triage workflow, if users without repo write access create issues github_token: ${{ secrets.GITHUB_TOKEN }}