GitHub Actions에서 WIF 사용하기
수명이 긴 API 키 대신 수명이 짧은 ID 토큰을 사용하여 GitHub Actions 워크플로를 Claude API에 인증합니다.
모든 GitHub Actions 워크플로 실행은 https://token.actions.githubusercontent.com에 있는 GitHub의 호스팅 발급자로부터 서명된 ID 토큰을 요청할 수 있습니다. "Workload Identity Federation"(워크로드 ID 페더레이션), 즉 WIF를 사용하면 워크플로가 해당 토큰을 수명이 짧은 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와 같은 다른 클레임)과 대조하여 어떤 워크플로 실행이 인증할 수 있는지 결정합니다.
사전 요구 사항
- WIF 개념에 대한 이해: 서비스 계정, 페더레이션 발급자, 페더레이션 규칙.
- 워크플로 파일을 편집하고
id-token: write권한을 부여할 수 있는 GitHub 리포지토리. - Anthropic 조직의 Claude Console에서 서비스 계정, 페더레이션 발급자, 페더레이션 규칙을 생성할 수 있는 권한.
- Anthropic 조직 ID. Claude Console의 Settings → Organization에서 확인할 수 있습니다.
워크플로 구성
GitHub는 명시적으로 요청하는 작업에만 ID 토큰을 발급합니다. 워크플로 또는 작업 수준에서 id-token: write 권한을 추가하세요:
permissions:
id-token: write
contents: read작업 내부에서 러너는 ACTIONS_ID_TOKEN_REQUEST_URL과 ACTIONS_ID_TOKEN_REQUEST_TOKEN이라는 두 개의 환경 변수를 노출합니다. 요청 토큰을 bearer 자격 증명으로, 선택한 audience를 쿼리 매개변수로 사용하여 요청 URL을 호출한 다음, 반환된 "JSON Web Token"(JSON 웹 토큰), 즉 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 subject 클레임 참조를 참조하세요.
Anthropic 구성
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가 발급한 각 ID 토큰은 발급 후 약 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 값이 반환됩니다. 교환이 거부되면 어떤 검사가 실패했든 고정 메시지 Authentication failed와 함께 불투명한 401 authentication_error가 반환됩니다. 대부분의 경우 거부 사유는 인증 기록 페이지의 해당 시도 항목에 기록되며, 실패한 교환 문제 해결에서 검사를 순서대로 안내합니다. GitHub Actions 측에서 가장 흔한 원인은 sub 클레임 형식이 일치하지 않는 것입니다(마지막 세그먼트가 ref:..., environment:..., pull_request 이벤트 간에 달라짐). 이 경우 기록 항목에 match_subject_prefix 사유가 표시됩니다.
인증할 수 있는 워크플로 제한
규칙의 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에서 필수 검토자로 해당 환경을 게이트하세요.
다음 단계
- Workload Identity Federation: 전체 설정 안내, 환경 변수, 자격 증명 우선순위.
- 인증: 페더레이션과 API 키의 비교.
Was this page helpful?