Каждый запуск рабочего процесса GitHub Actions может запросить подписанный токен идентификации у размещённого издателя GitHub по адресу https://token.actions.githubusercontent.com. С помощью Workload Identity Federation (федерация удостоверений рабочих нагрузок) ваш рабочий процесс обменивает этот токен на краткосрочный токен доступа Anthropic, поэтому ваши задания CI могут вызывать Claude API без секрета ANTHROPIC_API_KEY, хранящегося в вашем репозитории.
Утверждение sub токена кодирует контекст репозитория и триггера. Для push в ветку оно имеет форму 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 выдаёт токен идентификации только тем заданиям, которые явно его запрашивают. Добавьте разрешение id-token: write на уровне рабочего процесса или задания:
permissions:
id-token: write
contents: readВнутри задания исполнитель предоставляет две переменные окружения: ACTIONS_ID_TOKEN_REQUEST_URL и ACTIONS_ID_TOKEN_REQUEST_TOKEN. Вызовите URL запроса с токеном запроса в качестве bearer-учётных данных и выбранной вами аудиторией в качестве параметра запроса, затем запишите возвращённый 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-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"
}Полный список форматов sub см. в справочнике GitHub по утверждению subject в OIDC.
В Claude Console откройте Settings → Workload identity, нажмите Connect workload и выберите плитку GitHub Actions. Мастер проведёт вас через регистрацию издателя, создание сервисного аккаунта и создание правила федерации.
Мастер создаёт эти ресурсы за вас. Используйте следующие значения независимо от того, вводите ли вы их в мастере или отправляете в Admin API:
Издатель федерации: GitHub публикует свой документ обнаружения OIDC и JWKS публично, поэтому используйте режим обнаружения. Anthropic автоматически обновляет ключи, когда GitHub их ротирует.
{
"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
}Будьте настолько конкретны, насколько позволяет рабочая нагрузка. Ослабляйте 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-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 токен идентификации истекает примерно через пять минут после выдачи. Конечная точка запроса токена (ACTIONS_ID_TOKEN_REQUEST_URL) остаётся действительной в течение всего задания, поэтому вы можете получить свежий токен в любой момент. SDK обменивает токен при первом использовании и кэширует полученный токен доступа Anthropic. Для заданий, которые выполняются дольше, чем время жизни токена Anthropic, SDK повторно читает ANTHROPIC_IDENTITY_TOKEN_FILE при каждом обновлении, поэтому периодически повторяйте шаг получения токена (или оберните его в фоновый цикл), чтобы файл оставался актуальным. В качестве альтернативы передайте SDK колбэк-провайдер токенов, который вызывает ACTIONS_ID_TOKEN_REQUEST_URL напрямую вместо использования пути к файлу.
Успешный обмен возвращает access_token, начинающийся с sk-ant-oat01-, и значение expires_in в секундах. При 400 invalid_grant см. Устранение неполадок при неудачном обмене; наиболее распространённая причина на стороне GitHub Actions — несоответствие формата утверждения sub (его конечный сегмент варьируется между событиями ref:..., environment:... и pull_request).
subject_prefix вида repo:your-org/* сам по себе соответствует каждому репозиторию в вашей организации, а без ограничения ref он также соответствует запускам pull_request, инициированным из форков. Любой, кто может открыть pull request к соответствующему репозиторию, мог бы получить федеративный токен Anthropic.
Ограничьте блок match правила до самой узкой области, подходящей для вашего случая использования:
subject_prefix: "repo:your-org/your-repo:*", чтобы другие репозитории в организации не соответствовали правилу."ref": "refs/heads/main" (или вашу релизную ветку) в claims, чтобы запуски pull request и функциональные ветки не соответствовали правилу."repository_owner": "your-org" в claims в качестве проверки глубокоэшелонированной защиты от пограничных случаев разбора sub.subject_prefix: "repo:your-org/your-repo:environment:production" и защитите это окружение обязательными рецензентами в GitHub.Was this page helpful?