Jeder GitHub Actions-Workflow-Lauf kann ein signiertes Identity-Token vom gehosteten Issuer von GitHub unter https://token.actions.githubusercontent.com anfordern. Mit "Workload Identity Federation" (Workload-Identitätsföderation) tauscht dein Workflow dieses Token gegen ein kurzlebiges Anthropic-Access-Token aus, sodass deine CI-Jobs die Claude API aufrufen können, ohne dass ein ANTHROPIC_API_KEY-Secret in deinem Repository gespeichert ist.
Der sub-Claim des Tokens kodiert das Repository und den Trigger-Kontext. Für einen Push auf einen Branch hat er die Form repo:<owner>/<repo>:ref:refs/heads/<branch>. Pull-Request-Läufe verwenden repo:<owner>/<repo>:pull_request, und umgebungsgesteuerte Deployments verwenden repo:<owner>/<repo>:environment:<name>. Deine Federation-Regel gleicht diesen Claim (und andere, wie repository_owner und ref) ab, um zu entscheiden, welche Workflow-Läufe sich authentifizieren dürfen.
id-token: write erteilen kannst.GitHub stellt ein Identity-Token nur für Jobs aus, die es explizit anfordern. Füge die Berechtigung id-token: write auf Workflow- oder Job-Ebene hinzu:
permissions:
id-token: write
contents: readInnerhalb des Jobs stellt der Runner zwei Umgebungsvariablen bereit: ACTIONS_ID_TOKEN_REQUEST_URL und ACTIONS_ID_TOKEN_REQUEST_TOKEN. Rufe die Request-URL mit dem Request-Token als Bearer-Credential und deiner gewählten Audience als Query-Parameter auf, und schreibe dann das zurückgegebene "JSON Web Token" (JSON-Web-Token), oder JWT, in eine Datei:
- 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-jwtWenn du JavaScript bevorzugst, stellt actions/github-script dieselbe Funktionalität über core.getIDToken(audience) bereit:
- 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);Das dekodierte Token enthält Claims, die den Workflow-Lauf beschreiben. Deine Federation-Regel gleicht diese ab:
{
"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"
}Siehe GitHubs OIDC-Subject-Claim-Referenz für die vollständige Liste der sub-Formate.
Folge der Einrichtungsanleitung, um einen Federation-Issuer zu registrieren, einen Anthropic-Service-Account zu erstellen und eine Federation-Regel in der Claude Console anzulegen. Verwende diese GitHub Actions-spezifischen Werte.
Federation-Issuer: GitHub veröffentlicht sein OIDC-Discovery-Dokument und JWKS öffentlich, verwende also den Discovery-Modus. Anthropic aktualisiert die Schlüssel automatisch, wenn GitHub sie rotiert.
{
"name": "github-actions",
"issuer_url": "https://token.actions.githubusercontent.com",
"jwks_source": "discovery"
}Federation-Regel: Matche nur die Workflow-Läufe, denen du vertrauen möchtest. Siehe Einschränken, welche Workflows sich authentifizieren können, um zu erfahren, wie du diese Claims sicher eingrenzt.
{
"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
}Sei so spezifisch, wie es der Workload erlaubt. Lockere subject_prefix nur dann auf repo:your-org/your-repo:* (kombiniert mit einer claims.ref-Einschränkung), wenn die Regel mehrere Event-Typen aus demselben Repository matchen muss, da das abschließende Segment von sub zwischen ref:...-, environment:...- und pull_request-Events variiert.
Setze die Federation-Umgebungsvariablen für den Job und rufe das SDK wie gewohnt auf. Anthropic() liest ANTHROPIC_IDENTITY_TOKEN_FILE, tauscht das JWT bei der ersten Anfrage aus und aktualisiert das Access-Token automatisch, bevor es abläuft.
import anthropic
# Liest ANTHROPIC_FEDERATION_RULE_ID, ANTHROPIC_ORGANIZATION_ID,
# ANTHROPIC_SERVICE_ACCOUNT_ID, ANTHROPIC_WORKSPACE_ID und ANTHROPIC_IDENTITY_TOKEN_FILE
# aus der Job-Umgebung.
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)Jedes von GitHub ausgestellte Identity-Token läuft etwa fünf Minuten nach der Ausstellung ab. Der Token-Request-Endpunkt (ACTIONS_ID_TOKEN_REQUEST_URL) bleibt für den gesamten Job gültig, sodass du jederzeit ein neues Token abrufen kannst. Das SDK tauscht das Token bei der ersten Verwendung aus und cacht das resultierende Anthropic-Access-Token. Für Jobs, die länger laufen als die Lebensdauer des Anthropic-Tokens, liest das SDK ANTHROPIC_IDENTITY_TOKEN_FILE bei jeder Aktualisierung erneut ein – führe den Fetch-Schritt also regelmäßig erneut aus (oder verpacke ihn in eine Hintergrundschleife), um die Datei aktuell zu halten. Alternativ kannst du dem SDK einen Token-Provider-Callback übergeben, der ACTIONS_ID_TOKEN_REQUEST_URL direkt aufruft, anstatt den Dateipfad zu verwenden.
Ein erfolgreicher Austausch gibt ein access_token zurück, das mit sk-ant-oat01- beginnt, sowie einen expires_in-Wert in Sekunden. Bei 400 invalid_grant siehe Fehlerbehebung bei einem fehlgeschlagenen Austausch; die häufigste Ursache auf GitHub Actions-Seite ist, dass das Format des sub-Claims nicht übereinstimmt (sein abschließendes Segment variiert zwischen ref:...-, environment:...- und pull_request-Events).
Ein subject_prefix von repo:your-org/* allein matcht jedes Repository in deiner Organisation, und ohne eine ref-Einschränkung matcht er auch pull_request-Läufe, die von Forks ausgelöst werden. Jeder, der einen Pull Request gegen ein passendes Repository öffnen kann, könnte ein föderiertes Anthropic-Token erhalten.
Beschränke den match-Block der Regel auf den engsten Bereich, der zu deinem Anwendungsfall passt:
subject_prefix: "repo:your-org/your-repo:*", damit andere Repositories in der Organisation nicht matchen."ref": "refs/heads/main" (oder deinen Release-Branch) unter claims hinzu, damit Pull-Request-Läufe und Feature-Branches nicht matchen."repository_owner": "your-org" unter claims als zusätzliche Absicherung (Defense-in-Depth) gegen Grenzfälle beim Parsen von sub hinzu.subject_prefix: "repo:your-org/your-repo:environment:production" und schütze diese Umgebung in GitHub mit erforderlichen Reviewern.Was this page helpful?