Ogni esecuzione di un workflow di GitHub Actions può richiedere un token di identità firmato dall'issuer ospitato da GitHub all'indirizzo https://token.actions.githubusercontent.com. Con la "Workload Identity Federation" (federazione delle identità dei workload), il tuo workflow scambia quel token con un token di accesso Anthropic di breve durata, così i tuoi job CI possono chiamare l'API di Claude senza un secret ANTHROPIC_API_KEY memorizzato nel tuo repository.
Il claim sub del token codifica il repository e il contesto del trigger. Per un push su un branch ha la forma repo:<owner>/<repo>:ref:refs/heads/<branch>. Le esecuzioni di pull request usano repo:<owner>/<repo>:pull_request, e i deployment vincolati a un environment usano repo:<owner>/<repo>:environment:<name>. La tua regola di federazione effettua il match su questo claim (e su altri, come repository_owner e ref) per decidere quali esecuzioni di workflow sono autorizzate ad autenticarsi.
id-token: write.GitHub emette un token di identità solo ai job che lo richiedono esplicitamente. Aggiungi il permesso id-token: write a livello di workflow o di job:
permissions:
id-token: write
contents: readAll'interno del job, il runner espone due variabili d'ambiente: ACTIONS_ID_TOKEN_REQUEST_URL e ACTIONS_ID_TOKEN_REQUEST_TOKEN. Chiama l'URL di richiesta usando il request token come credenziale bearer e l'audience scelta come parametro di query, quindi scrivi il "JSON Web Token" (token web JSON), o JWT, restituito in un file:
- 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-jwtSe preferisci JavaScript, actions/github-script espone la stessa funzionalità tramite 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);Il token decodificato contiene claim che descrivono l'esecuzione del workflow. La tua regola di federazione effettua il match su questi:
{
"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"
}Consulta il riferimento di GitHub sui subject claim OIDC per l'elenco completo dei formati di sub.
Segui la procedura guidata di configurazione per registrare un federation issuer, creare un service account Anthropic e creare una federation rule nella Claude Console. Usa questi valori specifici per GitHub Actions.
Federation issuer: GitHub pubblica il suo documento di discovery OIDC e il JWKS pubblicamente, quindi usa la modalità discovery. Anthropic aggiorna automaticamente le chiavi quando GitHub le ruota.
{
"name": "github-actions",
"issuer_url": "https://token.actions.githubusercontent.com",
"jwks_source": "discovery"
}Federation rule: Effettua il match solo sulle esecuzioni di workflow che intendi considerare attendibili. Consulta Limitare quali workflow possono autenticarsi per sapere come definire l'ambito di questi claim in modo sicuro.
{
"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
}Sii il più specifico possibile in base al workload. Allenta subject_prefix a repo:your-org/your-repo:* (abbinato a un vincolo claims.ref) solo se la regola deve corrispondere a più tipi di evento dallo stesso repository, poiché il segmento finale di sub varia tra eventi ref:..., environment:... e pull_request.
Imposta le variabili d'ambiente di federazione sul job e chiama l'SDK normalmente. Anthropic() legge ANTHROPIC_IDENTITY_TOKEN_FILE, scambia il JWT alla prima richiesta e aggiorna automaticamente il token di accesso prima che scada.
import anthropic
# Legge ANTHROPIC_FEDERATION_RULE_ID, ANTHROPIC_ORGANIZATION_ID,
# ANTHROPIC_SERVICE_ACCOUNT_ID, ANTHROPIC_WORKSPACE_ID e ANTHROPIC_IDENTITY_TOKEN_FILE
# dall'ambiente del job.
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)Ogni token di identità emesso da GitHub scade circa cinque minuti dopo l'emissione. L'endpoint di richiesta del token (ACTIONS_ID_TOKEN_REQUEST_URL) rimane valido per l'intero job, quindi puoi recuperare un token nuovo in qualsiasi momento. L'SDK scambia il token al primo utilizzo e memorizza in cache il token di accesso Anthropic risultante. Per i job che durano più a lungo della durata del token Anthropic, l'SDK rilegge ANTHROPIC_IDENTITY_TOKEN_FILE a ogni refresh, quindi riesegui periodicamente lo step di fetch (o inseriscilo in un loop in background) per mantenere il file aggiornato. In alternativa, passa all'SDK una callback token-provider che chiami direttamente ACTIONS_ID_TOKEN_REQUEST_URL invece di usare il percorso del file.
Uno scambio riuscito restituisce un access_token che inizia con sk-ant-oat01- e un valore expires_in in secondi. In caso di 400 invalid_grant, consulta Risolvere i problemi di uno scambio fallito; la causa più comune lato GitHub Actions è il formato del claim sub che non corrisponde (il suo segmento finale varia tra eventi ref:..., environment:... e pull_request).
Un subject_prefix di repo:your-org/* da solo corrisponde a ogni repository nella tua organizzazione e, senza un vincolo ref, corrisponde anche alle esecuzioni pull_request attivate da fork. Chiunque possa aprire una pull request verso un repository corrispondente potrebbe ottenere un token Anthropic federato.
Restringi il blocco match della regola all'ambito più ristretto adatto al tuo caso d'uso:
subject_prefix: "repo:your-org/your-repo:*" in modo che gli altri repository nell'organizzazione non corrispondano."ref": "refs/heads/main" (o il tuo branch di release) sotto claims in modo che le esecuzioni di pull request e i feature branch non corrispondano."repository_owner": "your-org" sotto claims come controllo di difesa in profondità contro casi limite nel parsing di sub.subject_prefix: "repo:your-org/your-repo:environment:production" e proteggi quell'environment con reviewer obbligatori in GitHub.Was this page helpful?