
目次
- 1 user@sinyblog:~/article ❯ 01_source.mdこの記事の出典:Anthropic 公式ドキュメント
- 2 user@sinyblog:~/article ❯ 02_why_keys_scare_us.mdなぜ「API キー」はそんなに怖いのか
- 3 user@sinyblog:~/article ❯ 03_one_minute_summary.md結論:WIF を 1 分で理解する
- 4 user@sinyblog:~/article ❯ 04_how_it_works.md仕組み図解:JWT が Anthropic トークンに化けるまで
- 5 user@sinyblog:~/article ❯ 05_three_resources.md登場人物 3 つだけ覚えれば OK
- 6 user@sinyblog:~/article ❯ 06_local_handson.md最短ハンズオン:自分の PC で「鍵なし Claude」を 5 分で動かす
- 7 user@sinyblog:~/article ❯ 07_github_actions.md応用編:CI/CD(GitHub Actions)から鍵を消す
- 8 user@sinyblog:~/article ❯ 08_migrate_safely.md既存ワークロードを「無停止で」移行する 4 ステップ
- 9 user@sinyblog:~/article ❯ 09_token_lifecycle.mdトークンの寿命と自動リフレッシュ
- 10 user@sinyblog:~/article ❯ 10_three_pitfalls.md初心者がハマる 3 つの罠
- 11 user@sinyblog:~/article ❯ 99_summary.mdまとめ
API キーを Git に push してしまった、.env に置いたまま忘れた、ローテーションが面倒で結局放置——この「静的 API キー問題」に、Anthropic 公式から正面突破の解答が出ました。キーレス認証(Workload Identity Federation, WIF)です。本記事は、OAuth も OIDC も初めてという方が、まずは自分のローカル PC から「API キーを 1 個も発行せず」に Claude を呼べるところまで、世界一丁寧に手取り足取り進めます。コマンド 5 つだけで完了する最短ハンズオン付き。所要時間は読んで実装まで約 20 分です。
user@sinyblog:~/article ❯ 01_source.mdこの記事の出典:Anthropic 公式ドキュメント
本記事は Anthropic の公式ドキュメント Workload Identity Federation[1] および Use WIF with GitHub Actions[2] を一次情報として、初心者向けに再構成したものです。仕様の細部や最新の挙動は公式ドキュメントを必ず参照してください。コマンド例や設定 JSON はすべて公式準拠で、コピペで動作します。
「API キーは知っているけれど、OIDC や JWT の話になると一気に手が止まる」という方を想定しています。仕組み(Why)と最短実装(How)を分けて書いているので、急ぐ方は ch06 から読み始めても OK です。本文中の [n] は記事末の References に対応します。
user@sinyblog:~/article ❯ 02_why_keys_scare_us.mdなぜ「API キー」はそんなに怖いのか
Claude API を使うとき、誰もが最初に発行するのが sk-ant-api03-xxxxx... という静的な API キーです。便利ですが、運用に乗せた瞬間に次のリスクを抱え込みます。
- 有効期限がない。一度漏れたら、運営者が手で revoke するまで永遠に使われ続ける。
- CI/CD のシークレットに置きっぱなし。GitHub Actions の Secrets、CircleCI の環境変数、社内の
.env……どこに何件埋まっているか、もう誰も把握していない。 - ローテーションが激痛。新キー発行 → 全環境で差し替え → 旧キー破棄、を四半期ごとにやる気力が湧かない。
- 誤コミット事故が後を絶たない。
.envを間違って push、Slack に値を貼ってしまう、退職者の手元に残る、など。
Anthropic の WIF ドキュメントは、この問題を端的に「長寿命の静的シークレットを、数分で失効する短命トークンに置き換える」と表現しています[1]。
Workload Identity Federation strengthens your security posture by removing static credentials from Anthropic's surface and replacing them with tokens that expire in minutes rather than never.
Anthropic Docs — Workload Identity Federation / [1]
user@sinyblog:~/article ❯ 03_one_minute_summary.md結論:WIF を 1 分で理解する
細かい話に入る前に、まず結論を 1 行で。
WIF とは、「あなたが既に持っている ID プロバイダ(GitHub・AWS・GCP・Azure など)が発行した署名付きトークン」を、Anthropic に提示して、その場で短命の Claude API トークンに引き換える仕組み。
銀行の窓口に運転免許証を提示すると、その日 1 日だけ有効な番号札がもらえる——あのイメージに近いです。免許証(GitHub OIDC トークン)はあなたの環境に最初から発行されているもので、銀行(Anthropic)はそれを検証して短命な番号札(sk-ant-oat01-...)を返します。番号札はすぐ失効するので、漏れても被害は数分で止まる。これが WIF の本質です。
| 従来の API キー | WIF(キーレス認証) | |
|---|---|---|
| 有効期限 | 無期限(手動 revoke のみ) | デフォルト 1 時間、最短 60 秒 |
| CI Secrets への保存 | 必須(漏洩リスク) | 不要 |
| ローテーション | 手動・四半期ごと | SDK が自動で再発行 |
| 監査 | 「誰が使ったか」追えない | Service Account 単位で識別可能 |
| 初期セットアップ | 5 分 | 15〜20 分(一度きり) |
user@sinyblog:~/article ❯ 04_how_it_works.md仕組み図解:JWT が Anthropic トークンに化けるまで
WIF の動作は、たった 3 ステップに分解できます[1]。
- あなたの ID プロバイダが JWT を発行する。GitHub Actions なら
ACTIONS_ID_TOKEN_REQUEST_URL経由で、AWS なら EKS の Projected Token、Kubernetes なら ServiceAccount Token として、環境に最初から備わっている仕組みで取得できます。手動で何かを管理する必要はありません。 - SDK がその JWT を Anthropic に持っていく。
POST /v1/oauth/tokenエンドポイントに、JWT をassertionとして渡します。Anthropic 側は事前に登録された JWKS(公開鍵セット)で署名を検証し、ルールに合致すればsk-ant-oat01-...という短命アクセストークンを返します。プロトコルは RFC 7523 のjwt-bearer[3]。OAuth 2.0 標準なので、各言語の SDK が自動でやってくれます。 - SDK は短命トークンで API を呼び続ける。期限が切れる 120 秒前から自動で再交換し、API キーのときと同じ感覚で
client.messages.create(...)が動きます。
つまり、あなたのコードは 1 行も変えなくていいのがポイントです。Anthropic() を引数なしで呼び出すだけで、SDK が環境変数を見て勝手に WIF モードに入ります。
user@sinyblog:~/article ❯ 05_three_resources.md登場人物 3 つだけ覚えれば OK
Claude Console で WIF を設定するときに登場するリソースは、たった 3 種類です。最初に頭に入れておくと迷子になりません。
| リソース | ID プレフィクス | 役割 |
|---|---|---|
| Service Account(サービスアカウント) | svac_... |
「人間ではない実行主体」を表す ID。発行されるトークンは「この svac として」API を叩くことになる。Workspace 単位で利用権限を付与する。 |
| Federation Issuer(フェデレーション発行元) | fdis_... |
「この外部 IdP からの JWT は信用する」と Anthropic に伝える登録。GitHub Actions・AWS・GCP などをそれぞれ別個に登録する。 |
| Federation Rule(フェデレーションルール) | fdrl_... |
「issuer X からの JWT で、claim が Y なら、svac Z として通す」というマッチング規則。セキュリティの中核。 |
「Service Account = 名前付きの非人間ユーザー」「Issuer = ID プロバイダの登録」「Rule = どの JWT を、どの Service Account として受け入れるかの認可ポリシー」。API キーは"鍵そのもの"だが、Service Account は"鍵を都度発行してもらう人"——という所有関係の違いが分かれば理解できたも同然です[1]。
user@sinyblog:~/article ❯ 06_local_handson.md最短ハンズオン:自分の PC で「鍵なし Claude」を 5 分で動かす
CI/CD やクラウドの話に進む前に、まず自分のローカル PC で「API キーを 1 個も発行せずに Claude を呼ぶ」体験から始めましょう。これが WIF の世界の入口で、登録 → ターミナルで 5 コマンド → Python 1 ファイルで完結します。
Anthropic アカウント(Console にログインできる)/Python 3.9 以上/ブラウザ。それだけです。API キーの発行画面は触りません。
本ハンズオンで使う「ブラウザ経由のインタラクティブ OAuth」は anthropic-cli v1.5.0 で初めて追加された機能です[6]。古いバージョンでは ant auth サブコマンドが存在しません。必ず最新版をインストールしてください。
Step 1:Anthropic CLI(ant)をインストールする
Anthropic が公式提供している CLI ツールが ant です。これがブラウザ認証の入口になります。残念ながら pip install では入りません。OS ごとにインストール方法が異なるので、自分の環境に合うものを選んでください[7]。
macOS の場合(Homebrew)
brew install anthropics/tap/ant
Linux / WSL の場合
VERSION=1.5.0
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m | sed -e 's/x86_64/amd64/' -e 's/aarch64/arm64/')
curl -fsSL "https://github.com/anthropics/anthropic-cli/releases/download/v${VERSION}/ant_${VERSION}_${OS}_${ARCH}.tar.gz" \
| sudo tar -xz -C /usr/local/bin antWindows の場合(3 つの選択肢)
Windows には専用インストーラがまだ用意されていません(2026-05 時点)。下のいずれかを選びます。初心者には選択肢 A(WSL)が最もハマりにくいのでおすすめです。
- 選択肢 A: WSL(Windows Subsystem for Linux)を使う — Windows 11 なら PowerShell で
wsl --installを 1 回実行 → 再起動 → Ubuntu のターミナルが開く → 上の「Linux / WSL の場合」のコマンドを実行。以降のハンズオンも全部 Ubuntu 側で進める。 - 選択肢 B: Go から入れる — すでに Go 1.22+ が入っているなら以下 1 行。
$(go env GOPATH)/binにant.exeが置かれるので、そのフォルダを PATH に追加すること(cmd.exe でsetx PATH "%PATH%;%USERPROFILE%\go\bin")。 - 選択肢 C: GitHub Releases から zip / exe を直接落とす — releases ページ で
ant_1.5.0_windows_amd64.*のような Windows 用アセットをダウンロード → 展開 →ant.exeを任意のフォルダに置いて PATH に追加。
go install github.com/anthropics/anthropic-cli/cmd/ant@latest
インストール確認
どの方法でも、最後にこれが通れば成功です(バージョンが 1.5.0 以上であることも確認)。
ant --version
'ant' は認識されません と出たら
これは PATH が通っていないサインです。① Go install の場合は %USERPROFILE%\go\bin を、② バイナリ直配置の場合はその配置フォルダを、それぞれ環境変数 PATH に追加し、ターミナルを開き直すと通ります。WSL の場合は WSL のシェル側で実行してください(Windows 側 cmd.exe からは見えません)。
このあと ant auth login で保存される認証情報は、OS ごとに違うフォルダに書かれます[5]。WSL(Linux)の中で認証 → Windows 側の cmd / PowerShell で Python 実行、は動きません(ファイルシステムが分離しているため、Python から認証情報が見えない)。
つまり、Step 1 で選んだ環境を最後まで貫くのが鉄則です:
- 選択肢 A(WSL)を選んだ人 → Step 2 以降の
ant auth login・pip install・python hello.pyをすべて同じ WSL Ubuntu のターミナルで実行する。Windows のコマンドプロンプトには戻らない。認証情報の保存先は/home/<your-name>/.config/anthropic/ - 選択肢 B / C(Windows ネイティブ)を選んだ人 → Step 2 以降を Windows の cmd または PowerShell で実行する。認証情報の保存先は
%APPDATA%\Anthropic\
Step 2:ant auth login でブラウザ認証する
下のコマンドを叩くと、ブラウザが自動で開いて Anthropic の認証画面に飛びます。普段 Console にログインするのと同じ感覚で「Allow(許可)」をクリックすると、ターミナルに戻ってきます。これだけで認証情報がローカルプロフィールに保存されます。
ant auth login
このフローはAPI キーを 1 つも作りません。Anthropic アカウント自身が認証材料になります。.env ファイルにコピペする値も発行されません。
Step 3:認証ソースを確認する
ちゃんと認証できているか、SDK 側から見える形で確認します。
ant auth status
下のような出力が表示されたら成功です。
user@host:~$ ant auth status
Active profile: default (from active_config file)
Config dir: /home/<your-name>/.config/anthropic
Profile config: /home/<your-name>/.config/anthropic/configs/default.json
Credentials: /home/<your-name>/.config/anthropic/credentials/default.json
Credentials
Logged in to <your-org> as you@example.com
(active) * Profile (user_oauth) [via active_config] sk-ant-oat01-XXX...
expires: 2026-05-05T22:18:05+09:00 (in 8h0m0s)
scope: user:developer user:inference user:profile
organization: <your-org> (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
client_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Base URL
(active) * SDK default https://api.anthropic.com
Organization
(active) * Profile organization_id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Workspace
(active) * Workspace wrkspc_xxxxxxxxxxxxxxxxxxxxx (Default)
初めて見ると情報量が多くて圧倒されますが、本当に注目すべき行はたった 4 つです。下の表で「どこを見れば成功と分かるか」を整理しておきましょう。
| 注目する行 | 意味 | これを確認すると… |
|---|---|---|
Logged in to <org> as you@example.com |
あなたの Anthropic アカウントで認証済み | ログイン成功=Step 2 のブラウザ認証が完了している |
(active) * Profile (user_oauth) |
OAuth 経由のプロフィールがアクティブ | API キーではなくキーレス認証が選ばれている |
sk-ant-oat01-XXX... |
SDK が使う短命トークンの実体 | ch04 の図解で説明した「JWT を交換した短命トークン」がここに刻まれている |
expires: ... (in 8h0m0s) |
このトークンの残り寿命 | API キーと違って自動失効する。期限が切れる前に SDK が裏で再発行する |
scope 行(user:developer user:inference user:profile)は「このトークンで何ができるか」のリストで、ブラウザ認証では 個人開発者向けの権限が付与されます。一方、本記事 ch07 で扱う CI/CD のワークロード認証では workspace:developer という別のスコープになります(同じ枠組みで権限の単位だけ違う)。organization 行と workspace 行は「どの組織・どの Workspace で API を叩くか」の宛先で、複数組織に所属している方は意図した側に矢印((active))が立っているか必ず確認してください。
同時に、念のため ANTHROPIC_API_KEY 環境変数が残っていないことも確認しておきましょう(残っていると後述 ch10 の罠 1 を踏みます)。OS とシェルごとに確認方法が違うので、自分の環境のものを使ってください。
# 何も出力されなければ未設定(OK)。sk-ant-api03-... が出たら NG
echo "$ANTHROPIC_API_KEY"
REM "Environment variable ANTHROPIC_API_KEY not defined" と出れば OK
set ANTHROPIC_API_KEY
# 何も出力されなければ未設定(OK)
$env:ANTHROPIC_API_KEY
echo %ANTHROPIC_API_KEY% をやっても判定できない理由
cmd.exe には独特のクセがあって、未定義の変数は展開されず %ANTHROPIC_API_KEY% という文字列がそのまま画面に出ます(バグではなく仕様)。これだと「未設定」と「文字列として %ANTHROPIC_API_KEY% がセットされている」の区別がつきません。cmd.exe では必ず set ANTHROPIC_API_KEY(引数なし)を使ってください。未定義なら Environment variable ANTHROPIC_API_KEY not defined、定義済みなら ANTHROPIC_API_KEY=... という形で値が表示されます。
Step 4:Python の SDK をインストールする
pip install anthropic
Step 5:hello.py を書いて実行する
3 行で Claude を呼ぶスクリプトを作ります。API キーはコードのどこにも書きません。Anthropic() を引数なしで呼び出すと、SDK が Step 2 で保存したローカルプロフィールを自動で読みます[5]。
import anthropic
# api_key 引数は渡さない。
# SDK が ant auth login で保存されたプロフィールを自動で読み、
# 短命トークンを取得して API を叩く。
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": "こんにちは Claude、自己紹介してください"}],
)
print(message.content[0].text)
python hello.py
たとえば次のような応答が返ってきます(claude-sonnet-4-6 モデルでの実行例)。
(env) C:\tmp\claude>python hello.py
こんにちは!私はClaudeです。Anthropicが開発したAIアシスタントです。
## 私にできること:
- **会話・相談** — 日常的な質問や悩み相談
- **文章作成** — メール、レポート、創作など
- **情報提供** — 様々なトピックについての説明
- **分析・要約** — 文章の整理や要点まとめ
- **プログラミング** — コードの作成やデバッグ
- **語学サポート** — 翻訳や文法の説明
## 特徴:
- 日本語でも自然に会話できます 🇯🇵
- 誠実で、わからないことは「わからない」と答えます
- 有害なことや危険なことはお断りします
---
何かお手伝いできることはありますか?気軽に話しかけてください!😊ant v1.5.0 + Python 仮想環境((env))Claude の応答がターミナルに流れてきたら、ハンズオン完了です。.env も os.environ["ANTHROPIC_API_KEY"] も書いていないのに、API が動いている——これがキーレス認証の最初の手触りです。
SDK は資格情報を 5 階層で順番に探します[5]:① コンストラクタ引数 → ② ANTHROPIC_API_KEY 環境変数 → ③ 明示プロフィール → ④ WIF 環境変数 → ⑤ 暗黙のアクティブプロフィール。ant auth login は ⑤ にトークンを置くので、引数なしの Anthropic() でも勝手に見つけてくれるのです。
Could not resolve authentication method が出たら
下のような TypeError でスクリプトが落ちる場合、原因はほぼ 100% 「認証情報を保存した場所と Python を実行している場所がズレている」です。
TypeError: "Could not resolve authentication method.
Expected one of api_key, auth_token, or credentials to be set."
典型例:WSL で ant auth login したのに、Windows 側の cmd / PowerShell で python hello.py を実行している。
WSL の認証情報(/home/<your-name>/.config/anthropic/)は Windows 側の Python からは見えず、Windows の %APPDATA%\Anthropic\ も空っぽなので、SDK が「資格情報なし」と判断します。
解決:ant auth login を実行したのと同じターミナルで Python venv を作り直し、pip install anthropic と python hello.py を実行してください。WSL なら WSL の中で、Windows ネイティブなら Windows の中で完結させる、というのが鉄則です。ant auth status が通る画面で Python を動かす、と覚えておけば確実です。
user@sinyblog:~/article ❯ 07_github_actions.md応用編:CI/CD(GitHub Actions)から鍵を消す
ローカルが動いたら、次は CI/CD です。WIF が真価を発揮するのはここから。本セクションは「応用編」なので、最初の 1 周は「ふーんこんな感じで設定するんだ」と眺める程度で十分です。実際にチームで導入する段階で、本記事末の公式ガイド[2]と合わせて読み込んでください。
GitHub Actions での設定は、3 つのパーツを組み合わせます。
- Anthropic Console: ch05 で説明した 3 リソース(Issuer / Service Account / Federation Rule)を作成。Issuer URL は GitHub の固定値
https://token.actions.githubusercontent.comで、JWKS source はdiscovery(自動取得)。 - GitHub workflow:
permissions: id-token: writeを有効化して OIDC トークンを取得。これが「明示的に許可された job にのみ」発行される仕組みで、書き忘れると一発で詰まります。 - アプリコード: 変更なし。CI 側で 4 つの環境変数を渡すだけで、SDK が自動で WIF モードに入ります。
ワークフロー YAML の最小例(コピペで動く形):
name: Call Claude (keyless)
on: push
permissions:
id-token: write # ← OIDC トークンの発行スイッチ。忘れると 403
contents: read
jobs:
call-claude:
runs-on: ubuntu-latest
env:
ANTHROPIC_FEDERATION_RULE_ID: fdrl_...
ANTHROPIC_ORGANIZATION_ID: 00000000-0000-0000-0000-000000000000
ANTHROPIC_SERVICE_ACCOUNT_ID: svac_...
ANTHROPIC_IDENTITY_TOKEN_FILE: /tmp/gha-jwt
steps:
- uses: actions/checkout@v5
- 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 > "$ANTHROPIC_IDENTITY_TOKEN_FILE"
- name: Run your script
run: |
pip install anthropic
python hello.py # ← ch06 のスクリプトをそのまま流用できるそしてセキュリティの心臓部が Federation Rule の match ブロック。GitHub Actions の OIDC トークンには「どのリポジトリ・どのブランチで動いているジョブか」が sub クレームに刻まれている[4]ので、これを使って「main ブランチへの push でしか認証できない」と縛ります。
{
"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
}WIF は GitHub Actions 専用ではありません。AWS(EKS の IRSA や STS web identity)、Google Cloud(メタデータサーバ)、Azure(Managed Identity / Entra Workload ID)、自前 Kubernetes クラスタなど、OIDC を喋る IdP なら何でも同じ仕組みで繋がります。違うのは「JWT をどこから取ってくるか」だけで、Anthropic 側の設定(3 リソース)も SDK のコードも共通です。詳しくは公式の各プロバイダガイドを参照[1]。
user@sinyblog:~/article ❯ 08_migrate_safely.md既存ワークロードを「無停止で」移行する 4 ステップ
すでに API キーで動かしている本番ワークロードを切り替えるときは、並行運用 → 切り替え → 鍵削除の順で慎重に進めます。Anthropic 公式が推奨する手順です[1]。
- WIF を並行で構築する。Issuer・Service Account・Rule を作り、テスト Workflow で
sk-ant-oat01-...がもらえることを確認。ANTHROPIC_API_KEYはまだ残しておく。 - どちらが勝っているか確かめる。
ant auth statusを本番環境内で実行。資格情報の優先順位はAPI_KEY > PROFILE > FEDERATIONなので、キーが残っている限り WIF は使われない。 - あらゆる場所から
ANTHROPIC_API_KEYを消す。GitHub Secrets、Docker 環境変数、shell プロファイル、CircleCI、Vercel、社内の.env……漏れなく。再度ant auth statusで WIF が選ばれていることを確認。 - Anthropic Console で API キーを revoke。Settings → API keys から該当キーを削除。これで「鍵が世の中に存在しない」状態が完成。
SDK の資格情報優先順位上、ANTHROPIC_API_KEY 環境変数が 1 つでも残っていると、WIF の設定がいくら正しくてもそちらが優先されてしまいます。「移行したつもりが実は旧キーで動いていた」事故を防ぐには、必ず ant auth status でソースを確認してください[1]。
user@sinyblog:~/article ❯ 09_token_lifecycle.mdトークンの寿命と自動リフレッシュ
「短命トークンで運用が回るのか?」という不安に、SDK は二段階リフレッシュで答えます[1]。
| 段階 | タイミング | 挙動 |
|---|---|---|
| Advisory refresh(前倒し更新) | 有効期限の 120 秒前 | 新しい交換を試みる。失敗してもキャッシュ済みトークンで継続。 |
| Mandatory refresh(必須更新) | 有効期限の 30 秒前 | 失敗したらエラー。期限が近すぎて使い続けるのは危険、と判断。 |
さらに、Anthropic トークンの寿命は「rule で設定した値」と「上流 JWT の残り寿命の 2 倍」のうち短い方に揃えられます(最低 60 秒)。GitHub Actions の OIDC トークンは約 5 分しか持たないため、長時間ジョブでは Step を再実行して JWT ファイルを更新するなどの工夫が必要、という注釈が公式に明記されています[2]。
user@sinyblog:~/article ❯ 10_three_pitfalls.md初心者がハマる 3 つの罠
公式ドキュメントを読んでも、最初の導入で詰まるポイントは決まっています。先回りで回避しましょう。
ANTHROPIC_API_KEY がどこかに残る(ローカルハンズオンで最も多い)
ch06 のハンズオンで「動かない」「キー認証されちゃう」と詰まる原因のほぼ全てがこれです。shell プロファイル(~/.bashrc や ~/.zshrc、Windows ならユーザー環境変数)、過去の .env、Docker イメージに焼き込まれた env、IDE のターミナル設定……。1 箇所でも残ると WIF が黙ってバイパスされ、旧キーで動いてしまうので、必ず ant auth status で「実際にどのソースが選ばれているか」を確認すること。
permissions: id-token: write を書き忘れる
GitHub Actions の OIDC は明示的に許可された job にのみトークンを発行します。これを書き忘れると ACTIONS_ID_TOKEN_REQUEST_URL が空になり、curl が無言で失敗。エラーメッセージが「URL が空」程度しか出ないので、原因不明になりがち。CI 連携の最初に必ず確認するチェックポイントです。
subject_prefix を緩くしすぎる
repo:your-org/* のように組織全体にマッチさせると、その組織の誰でも、フォークからの PR を含めて、Anthropic トークンを取得できてしまいます。公式が「Anyone who can open a pull request against a matching repository could obtain a federated Anthropic token.」と明確に警告している通り[2]。必ず repo:your-org/your-repo:ref:refs/heads/main のようにリポジトリ+ブランチまで絞ること。ここが緩いと WIF の安全性は API キー以下に落ちます。
user@sinyblog:~/article ❯ 99_summary.mdまとめ
Workload Identity Federation は、これまで「個人開発者の頑張り」に押し付けられていた API キーの安全管理を、プラットフォーム側のプロトコルで終わらせる仕組みです。要点は 3 つ。
- 静的な API キーは過去のもの。GitHub・AWS・GCP・Azure・Okta など、すでに使っている ID プロバイダの JWT がそのまま認証材料になる[1]。
- 初回設定は 15〜20 分、その後はゼロメンテナンス。Service Account / Federation Issuer / Federation Rule の 3 リソースを作るだけで、SDK が JWT 交換とリフレッシュを自動でやってくれる。
- セキュリティの本丸は
matchブロック。subject_prefixを「リポジトリ+ブランチ」まで絞り、repository_ownerを claim でも縛る。ここを緩くすれば WIF の安全性は API キー以下に落ちるので、最重要ポイントとして覚えておく。
「まず自分の PC で、API キーを 1 個も発行せずに Claude を呼んでみる」を最初のゴールに、ch06 の 5 コマンドから手を動かしてみてください。動いた瞬間に WIF の世界観が腑に落ちます。そこまでいけば、ch07 の CI/CD 連携や ch08 の本番移行は「同じ仕組みのスケール違い」でしかないので、自然に導入できるようになります。設定ファイルが Git に入って履歴に残るので、後から「いつ・誰が・どう変えたか」が追えるのも、API キー時代にはなかった大きな利点です。