Claude Media
WIFをAdmin APIで管理する — サービスアカウント/issuer/ruleを操作

WIFをAdmin APIで管理する — サービスアカウント/issuer/ruleを操作

Workload Identity Federationのサービスアカウントとfederationイシュアー・ルールをAdmin APIから作成・一覧・アーカイブする手順。

WIFをAdmin APIで管理するとは

Workload Identity Federation(WIF)は、Claude ConsoleのConnect workloadウィザードから手動で設定するのが基本の入り口です。ただしサービスアカウント・federation issuer・federation ruleの3リソースは、Admin APIから直接作成・一覧・アーカイブもできます。これらのエンドポイントは、Admin APIの残り全体と同じ/v1/organizationsパスプレフィックスを共有します。組織を横断してfederation設定をInfrastructure as Codeとして持ちたい、CIから配線したい、複数組織に同じ構成を再現したいといった用途に向きます。

Oktaやgithub-actionsといった個別プロバイダーごとの連携手順はClaudeのWIFをOktaと連携する手順ClaudeのWIFをSPIFFE/SPIREと連携する手順で扱っており、本記事はプロバイダーを問わず「issuer・ruleそのものをどう操作するか」に絞ります。

前提条件: どのトークンで叩くか

ここで扱うエンドポイントはすべて、org:adminスコープを持つOAuthベアラートークンで認証します。このスコープは組織のadmin・owner・primary ownerロールを持つメンバーにのみ付与され、組織全体へのアクセス権になります(ワークスペースの紐づけは無視されます)。トークンの取得方法は2通りあり、権限が異なります。自分のログインから得たトークンは人間として、federationされたトークンはサービスアカウントとして動作し、後者はここで扱う操作の一部を実行できません。

対話的取得(自分の端末から): ant CLIでスコープを要求して専用プロファイルにログインし、ベアラートークンをexportします。

ant auth login --profile admin --scope "org:admin"
export ANTHROPIC_AUTH_TOKEN=$(ant auth print-credentials --profile admin --access-token)

--profile adminでのログインはorg:admin資格情報を専用のプロファイル名で保存すると同時にCLIのアクティブプロファイルにもしてしまい、exportした環境変数はそのシェル内のすべてのSDK・CLI呼び出しに適用されます。管理作業専用のシェルを用意し、作業が終わったら変数をunsetし、ant profile activate defaultでCLIを戻してください。対話的トークンは短命で、401が返り始めたらexportコマンドを再実行します(自動でリフレッシュされます)。SDKとant CLIはANTHROPIC_AUTH_TOKENを自動で読むので、同じシェルではANTHROPIC_API_KEYを未設定にしておきます(両方セットされているとクライアントによってはAPIキーを優先することがあります)。

ワークロードからの取得(CIと自動化): organization_roleadminのサービスアカウントを対象に、oauth_scope: org:adminのfederation ruleを作ります。このルール自体はClaude Console上でしか作れません。ワークロードに組織admin権限を与えるのは意図的な人間の操作であるべきで、自動化が自分自身にその権限を発行できてはならないためです。

ワークロードにWIF管理を任せる準備

Console側で作るorg:adminルールは1つで足ります。信頼できる1つのワークロード(たとえばインフラ用リポジトリのGitHub Actionsワークフロー)にorg:adminスコープを付与すれば、残りのfederation設定(issuerとワークスペース単位のすべてのrule)をこのAPI経由でInfrastructure as Codeに載せられます。

  1. ConsoleでOrg-adminルールを作る: Settings → Workload identityConnect workloadで自動化ワークロード用のfederation ruleを1つ作ります。Advanced rule optionsでOAuth scopeをorg:adminに設定すると、ウィザードがAdmin組織ロールを持つ新しいサービスアカウントを作成します(または既存のadminサービスアカウントを選ばせます)。
  1. ワークロードのidentity tokenを交換する: SDKやant CLIを使うワークロードは、交換処理自体を自分で書く必要はありません。federation用の環境変数をセットしてクライアントを引数無しで構築するだけで、推論用途と同じ仕組みが働きます。
export ANTHROPIC_FEDERATION_RULE_ID=fdrl_...        # 手順1で作ったorg:adminルール
export ANTHROPIC_ORGANIZATION_ID=00000000-0000-0000-0000-000000000000
export ANTHROPIC_SERVICE_ACCOUNT_ID=svac_...       # ルールのターゲットサービスアカウント
export ANTHROPIC_IDENTITY_TOKEN_FILE=/path/to/jwt  # またはANTHROPIC_IDENTITY_TOKEN
unset ANTHROPIC_API_KEY ANTHROPIC_AUTH_TOKEN       # どちらもfederationより優先されるため

複数のantコマンドを実行するワークロードでは、フラグや環境変数ではなくfederation profileを使います。federation profileはANTHROPIC_FEDERATION_RULE_IDなどの環境変数を設定ファイルにまとめ、identity tokenの取得元(ファイルかコマンド出力か)をantに一度だけ伝える仕組みです。フラグや環境変数のままだとプロセスごとにidentity tokenを再交換してしまいます。jtiクレームを含むトークン(GitHub Actionsのトークンはこれに該当)は1回しか使えないため、2回目のコマンドが拒否されます。curlで直接叩くワークロードは、通常のfederationワークロードと同じトークン交換を自分で行い、authorization: Bearerヘッダーに載せます。

  1. APIからissuerとruleを管理する: クライアントが構成できたら(curlの場合は交換で得たトークンをANTHROPIC_AUTH_TOKENに入れておけば)、これらのエンドポイントでfederation設定を作成・管理します。

すでにConnect workloadウィザードでissuer・サービスアカウント・ruleを作成済みなら、一覧エンドポイントで取得してInfrastructure as Codeの状態に取り込み、作り直さないようにします。

サービスアカウント

サービスアカウント(svac_...)は、federationされたトークンが代わりに動作する非人間のIDです。organization_roledeveloperに設定します。

curl --fail-with-body -sS "https://api.anthropic.com/v1/organizations/service_accounts" \
  -H "authorization: Bearer $ANTHROPIC_AUTH_TOKEN" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "name": "inference-worker",
    "organization_role": "developer"
  }'

作成するとsvac_...から始まるIDとnameorganization_rolecreated_atを含むオブジェクトが返ります。一覧は同じパスへのGET(limitは1〜100、既定20)、単体の参照・更新は/service_accounts/{service_account_id}へのGET/POSTです。サービスアカウントは、federationされたトークンがそのワークスペースで動作する前に、そのワークスペースのメンバーである必要があります。組織の既定ワークスペースには暗黙にメンバーとして扱われますが、他のワークスペースは/service_accounts/{service_account_id}/workspacesへのGETPOSTDELETEで明示的にメンバーシップを追加します。

Federation issuers

federation issuer(fdis_...)は、OIDCアイデンティティプロバイダーを組織に登録するリソースです。jwksフィールドは判別可能なユニオン型で、Anthropicが署名鍵をどう取得するかを決めます。

jwksの値使う場面
{"type": "discovery"}使う場面プロバイダーがissuer URLで/.well-known/openid-configurationを配信している
{"type": "explicit_url", "url": "..."}使う場面JWKSエンドポイントを直接指定する
{"type": "inline", "keys": [...]}使う場面公開インターネットから到達できないプロバイダー向けに鍵セットをアップロードする

GitHub Actionsをdiscoveryモードで登録する例:

curl --fail-with-body -sS "https://api.anthropic.com/v1/organizations/federation_issuers" \
  -H "authorization: Bearer $ANTHROPIC_AUTH_TOKEN" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "name": "github-actions",
    "issuer_url": "https://token.actions.githubusercontent.com",
    "jwks": {"type": "discovery"}
  }'

一覧・単体参照・更新のパスはサービスアカウントと同じ構造(/federation_issuers/federation_issuers/{issuer_id})です。OAuthで認証したAPI呼び出し元は、oauth_scopeworkspace:developerworkspace:inference以外(org:adminworkspace:manage_tunnelsなど)のruleが参照しているissuerを更新できません。bootstrap用のルールには専用のissuerを登録しておくと、ワークスペーススコープのrule側が使うissuerをAPI経由で更新できる状態を保てます。

Federation rules

federation rule(fdrl_...)は、issuerとサービスアカウントを結びつけます。issuerからのJWTがruleのmatch条件を満たせば、ruleのtargetとして動作するトークンを発行します。作成リクエストのworkspace_idが、そのワークスペースでruleを有効にします(workspace_idapplies_to_all_workspaces: trueのどちらかが作成時に必須)。

GitHub Actionsのmainブランチからのデプロイを、サービスアカウントとして動作させる例:

curl --fail-with-body -sS "https://api.anthropic.com/v1/organizations/federation_rules" \
  -H "authorization: Bearer $ANTHROPIC_AUTH_TOKEN" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "name": "gha-deploy",
    "issuer_id": "fdis_01ABCDEFabcdef0123456789XY",
    "match": {
      "subject_prefix": "repo:my-org/my-repo:ref:refs/heads/main",
      "claims": {"repository_owner": "my-org"}
    },
    "target": {
      "type": "service_account",
      "service_account_id": "svac_01ABCDEFabcdef0123456789XY"
    },
    "workspace_id": "wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ",
    "oauth_scope": "workspace:developer",
    "token_lifetime_seconds": 600
  }'

一覧はissuer_idでフィルタできます(GET /federation_rules?issuer_id=...)。ruleが動作できるワークスペースの追加・削除は/federation_rules/{rule_id}/workspacesへのGETPOSTDELETEです。リソース名は^[a-z0-9-]+$に一致し、1〜255文字、リソース種別ごとに組織内で一意である必要があります。

権限と制約

  • OAuth認証した呼び出し元は、oauth_scopeworkspace:developerworkspace:inferenceのruleしか作成・変更できません。org:adminworkspace:manage_tunnelsのような他のscopeを持つruleを作る・変えるにはConsoleを使います
  • oauth_scopeworkspace:developerworkspace:inference以外のruleが参照しているissuerは、OAuth呼び出し元からは更新できません
  • Admin APIキーはこれらのエンドポイントでは読み書きとも受け付けられません。必ずorg:adminのOAuthトークンを使います
  • oauth_scope: org:adminのruleは、organization_roleadminのサービスアカウントをtargetにしなければなりません

ページングとアーカイブ

サービスアカウント・federation issuer・federation ruleの一覧エンドポイントは、limit(1〜100、既定20)と前回レスポンスから取ったpageカーソルを受け付けます。レスポンスのnext_page値を次のリクエストのpageクエリパラメータに渡します。rule-workspacesサブリソースの一覧だけはページングなしで全件を返します。アーカイブ済みリソースは既定で一覧から除外され、include_archived=trueを付けると含まれます。

アーカイブはソフトデリートで冪等です。すでにアーカイブ済みのリソースをアーカイブしても成功します。一方、稼働中のfederation ruleがまだ参照しているissuerやサービスアカウントをアーカイブしようとすると400が返るため、先にruleをアーカイブする必要があります。

まとめ

WIFをAdmin APIで管理する構成は、ConsoleのConnect workloadウィザードで作ったorg:adminスコープのfederation ruleを1つの信頼できるワークロードに与えることから始まります。それ以降は、サービスアカウント・issuer・ruleの3つのリソースをコードで作成・一覧・アーカイブでき、組織を横断した再現や、CIからの継続的な構成管理が可能になります。個別プロバイダーの具体的な設定値(issuer URLの形式やmatchの組み方)は、Okta連携SPIFFE/SPIRE連携のようなプロバイダー別ガイドを参照してください。

この記事を共有:XはてブLinkedIn