---
title: SPIFFEでWIFを使用する
url: https://platform.claude.com/docs/ja/manage-claude/wif-providers/spiffe
description: SPIREまたはその他のSPIFFE準拠の発行者から取得したJWT-SVIDを使用して、SPIFFEワークロードをClaude APIに対して認証します。
---

[SPIFFE](https://spiffe.io/)は、ワークロードにアイデンティティを発行するためのCNCF標準です。[SPIRE](https://spiffe.io/docs/latest/spire-about/)はそのオープンソースのリファレンス実装であり、いくつかの商用製品もSPIFFE準拠のアイデンティティを発行します。Anthropicは、OIDC互換のJWT-SVIDを発行するあらゆるSPIFFE実装とフェデレーションします。実装の最新リストについては、SPIFFEプロジェクトサイトの[Commercial software that implements SPIFFE](https://spiffe.io/docs/latest/spiffe-about/overview/#commercial-software-that-implements-spiffe)を参照してください。

フェデレーションは、公開HTTPS URLにあるOIDCディスカバリードキュメントを介して行う方法（`discovery`モード、[URLの制約](https://platform.claude.com/docs/ja/manage-claude/wif-reference#url-fields)の対象）と、JWKSを直接登録する方法（`inline`モード）のいずれかで機能します。

JWT-SVID仕様では`sub`をワークロードのSPIFFE IDとして定義しており、SPIFFE Workload APIでは呼び出し側が取得時に`aud`を指定する必要があるため、これらのクレームは実装間で共通です。Anthropicはさらに`iss`と`iat`を必須としていますが、どちらもJWT-SVID仕様では必須とされていないため、両方を設定するように実装を構成してください（SPIREでは、`iss`はサーバー設定の`jwt_issuer`であり、`iat`は自動的に設定されます）。これらが整っていれば、このガイドの[Anthropicを構成する](https://platform.claude.com/docs/ja/manage-claude/wif-providers/spiffe#configure-anthropic)、[トークンを取得して使用する](https://platform.claude.com/docs/ja/manage-claude/wif-providers/spiffe#acquire-and-use-the-token)、[ルールのスコープを設定する](https://platform.claude.com/docs/ja/manage-claude/wif-providers/spiffe#scope-your-rule)の各セクションは、あらゆるSPIFFE実装に適用できます。

SPIFFEはすべてのワークロードに`spiffe://<trust-domain>/<path>`という形式の安定したアイデンティティURIを割り当て、SPIREはWorkload APIを通じてそのアイデンティティをJWT-SVIDとしてオンデマンドで発行します。JWT-SVIDは通常の署名付きJWTであり、その`sub`クレームはワークロードのSPIFFE IDで、`aud`クレームは取得時にワークロードが指定します。

SPIREトラストドメインから標準OIDCへの橋渡しとなるのが[SPIRE OIDC Discovery Provider](https://github.com/spiffe/spire/blob/main/support/oidc-discovery-provider/README.md)です。これはスタンドアロンのヘルパーで、トラストドメインのJWT署名鍵のために`/.well-known/openid-configuration`とJWKSエンドポイントを公開します。ディスカバリープロバイダーが稼働していれば、JWT-SVIDは他のOIDCトークンと同様に検証されます。ディスカバリーURLをフェデレーション発行者として登録し、ワークロードのSPIFFE IDに一致するフェデレーションルールを作成し、ワークロードがそのJWT-SVIDをAnthropicのトークン交換エンドポイントに提示するようにします。

このページの例ではSPIREを使用しており、SPIRE Agentが動作するあらゆる場所（Kubernetesポッド、仮想マシン、ベアメタルホスト）に適用できます。

<Note>
  KubernetesクラスターでSPIREを実行しておらず、代わりにクラスターネイティブのprojected service-accountトークンで認証したい場合は、[KubernetesでWIFを使用する](https://platform.claude.com/docs/ja/manage-claude/wif-providers/kubernetes)を参照してください。
</Note>

## 前提条件

* [WIFの概念](https://platform.claude.com/docs/ja/manage-claude/workload-identity-federation#concepts)（サービスアカウント、フェデレーション発行者、フェデレーションルール）に精通していること。
* ワークロードアイデンティティが発行されているSPIFFEデプロイメント（このページの例ではSPIRE ServerとAgentを使用）、およびClaude APIを呼び出す必要があるワークロードの登録エントリ。
* トラストドメイン用のOIDCディスカバリーエンドポイント（SPIREでは[OIDC Discovery Provider](https://github.com/spiffe/spire/blob/main/support/oidc-discovery-provider/README.md)）が公開到達可能なHTTPSエンドポイントで稼働していること、または`inline`登録用にエクスポートされたJWKS。
* JWT-SVIDの`iss`クレームを、フェデレーション発行者の`issuer_url`として登録する値に設定するようにSPIFFE発行者が構成されていること。`discovery`モードの場合、これはディスカバリーエンドポイントの公開URLです（SPIREではサーバー設定の`jwt_issuer`）。
* ワークロードがJWT-SVIDを利用できること。WIFはJWT-SVIDのみを受け付け、X.509-SVIDは受け付けません。
* Anthropic組織のClaude Consoleでサービスアカウント、フェデレーション発行者、フェデレーションルールを作成する権限。

JWT-SVIDを取得する際にリクエストするオーディエンス値は常に`https://api.anthropic.com`です。この値をspiffe-helperの`jwt_audience`、Workload APIの`FetchJWTSVID`呼び出し、およびフェデレーションルールの`audience`マッチャーで使用してください。

## SPIREを構成する

このセクションの手順はSPIRE固有のものです。別のSPIFFE発行者を使用する場合は、そのドキュメントに従ってOIDCディスカバリーエンドポイントとJWT-SVIDの取得を構成し、[Anthropicを構成する](https://platform.claude.com/docs/ja/manage-claude/wif-providers/spiffe#configure-anthropic)に進んでください。

すでにOIDC Discovery Providerと共にSPIREを運用している場合、Anthropicとのフェデレーションに必要なSPIRE側の要素は3つです。ディスカバリーURLと一致する`jwt_issuer`、Claude APIを呼び出すワークロードの登録エントリ、そしてそのワークロードがAnthropicオーディエンスでJWT-SVIDを取得する手段です。以下のサブセクションでそれぞれを順に説明します。構成スニペットはAnthropicフェデレーションに関連する設定のみを示しており、完全なSPIREデプロイメント構成ではありません。

<Tip>
  SPIREを初めてセットアップしますか？[SPIREクイックスタート](https://spiffe.io/docs/latest/try/)に従ってSPIRE ServerとAgentをデプロイし、次に[OIDC Discovery Provider](https://github.com/spiffe/spire/blob/main/support/oidc-discovery-provider/README.md)をSPIRE Serverと並ぶ別のサービスとして追加してください。ディスカバリーモードのフェデレーションは、プロバイダーがデプロイされ公開到達可能であることに依存します。プロバイダーはデフォルトのSPIREインストールには含まれていません。
</Tip>

### JWT発行者を確認する

Anthropicは、JWT-SVIDの`iss`クレームを登録済みのフェデレーション発行者と照合し、その発行者のディスカバリードキュメントからJWKSを取得することでJWT-SVIDを検証します。2つのSPIRE設定が同じURLで一致している必要があります。SPIRE Serverの`jwt_issuer`（発行されるすべてのJWT-SVIDの`iss`クレームになります）と、OIDC Discovery Providerの`domains`リスト（ディスカバリードキュメントとJWKSが提供されるホストを決定します）です。この共有URLがAnthropicに登録するものです。

トラストドメインと発行者URLは独立しています。トラストドメイン（`spiffe://prod.example.com`）は`sub`クレームのスコープを定めます。発行者URL（`https://oidc-discovery.prod.example.com`）はAnthropicが署名鍵を取得する場所です。両者がホスト名を共有する必要はありません。

SPIRE Serverの構成で`jwt_issuer`が設定され、ディスカバリープロバイダーの公開URLを指していることを確認してください。以下の例ではデフォルトのJWT-SVID有効期間も示しています。SPIREの組み込みデフォルトは5分で、継続的なローテーションが必要になるほど短い値です（[spiffe-helperを実行する](https://platform.claude.com/docs/ja/manage-claude/wif-providers/spiffe#run-spiffe-helper)を参照）。Anthropicのトークン交換エンドポイントは、有効期間がフェデレーション発行者に設定された最大値（デフォルトで1時間）を超えるアイデンティティトークンを拒否します（[検証ルール](https://platform.claude.com/docs/ja/manage-claude/wif-reference#validation-rules)を参照）。このチェックはSPIREだけでなくすべてのSPIFFE実装に適用されるため、`default_jwt_svid_ttl`（またはエントリごとのオーバーライド）をその最大値以下に保ってください。

```text server.conf
server {
    trust_domain         = "prod.example.com"
    jwt_issuer           = "https://oidc-discovery.prod.example.com"
    default_jwt_svid_ttl = "5m"
    # ...
}
```

OIDC Discovery Providerの構成では、同じホスト名が`domains`の下に記載されている必要があり、プロバイダーはSPIRE ServerのAPIソケットに到達できる必要があります。プロバイダーはディスカバリードキュメントとJWKSをHTTPS経由で提供します。組み込みのACMEサポートでTLSを終端するか、TLSを終端するロードバランサーを前段に配置してください。

```text oidc-discovery-provider.conf
domains = ["oidc-discovery.prod.example.com"]

server_api {
    address = "unix:///run/spire/sockets/private/api.sock"
}

acme {
    email        = "platform@example.com"
    tos_accepted = true
}
```

<Note>
  この例では`server_api`を使用しており、ディスカバリープロバイダーをSPIRE Serverの特権APIソケットに接続します。プロバイダーは`workload_api`ブロック（`socket_path`と`trust_domain`を含む）も受け付け、その場合は代わりにSPIRE AgentのWorkload APIを通じてバンドルを取得します。ディスカバリープロバイダーがServer APIにアクセスすべきでない場合や、Serverに到達できないノードで実行される場合に使用してください。
</Note>

### ワークロードを登録する

Claude APIを呼び出す各ワークロードには、ランタイムセレクターをSPIFFE IDにマッピングするSPIRE登録エントリが必要です。ワークロードがすでに登録されている場合は、そのSPIFFE IDを控えておいてください。これはフェデレーションルールの`subject_prefix`で使用します。登録されていない場合は登録してください。Kubernetesポッドの場合、セレクターは通常、名前空間とKubernetesサービスアカウントです。

```bash CLI
# NODE_UIDをノードのUIDに置き換えてください:
#   kubectl get node <node-name> -o jsonpath='{.metadata.uid}'
spire-server entry create \
    -spiffeID spiffe://prod.example.com/ns/inference/sa/worker \
    -parentID spiffe://prod.example.com/spire/agent/k8s_psat/prod-cluster/NODE_UID \
    -selector k8s:ns:inference \
    -selector k8s:sa:worker
```

<Note>
  示されている`parentID`は、単一ノードの自動生成されたエージェントIDです。クラスター全体で登録するには、[SPIRE Kubernetesクイックスタート](https://spiffe.io/docs/latest/try/getting-started-k8s/)と同様に、エントリの親を[ノードエイリアス](https://spiffe.io/docs/latest/deploying/registering/#mapping-workloads-to-multiple-nodes)にして、すべてのノード上のワークロードに一致するようにしてください。
</Note>

Kubernetes外のワークロードは、`unix:uid:1000`などのホストレベルのセレクターを使用します（`unix:path`も利用可能ですが、エージェントのunixワークロードアテスター構成で`discover_workload_path = true`が必要です）。[spire-controller-manager](https://github.com/spiffe/spire-controller-manager)を実行しているクラスターでは、`spire-server entry create`を直接呼び出す代わりに、`ClusterSPIFFEID`カスタムリソースでエントリを宣言できます。

### spiffe-helperを実行する

[spiffe-helper](https://github.com/spiffe/spiffe-helper)は、SPIRE Agentソケットに接続し、指定されたオーディエンスのJWT-SVIDを取得してファイルに書き込み、有効期限前に再取得するサイドカーユーティリティです。ヘルパーはデフォルトでデーモンモードで実行されます。以下の例では`daemon_mode = true`を明示的に設定しています。

```text helper.conf
agent_address = "/run/spire/sockets/agent.sock"
# The JWT-SVID file is written under cert_dir
cert_dir      = "/var/run/secrets/anthropic.com"
daemon_mode   = true

jwt_svids = [{
    jwt_audience       = "https://api.anthropic.com"
    jwt_svid_file_name = "token"
}]
```

Kubernetesでは、spiffe-helperをサイドカーコンテナとして実行し、メモリバックの`emptyDir`ボリューム（`medium: Memory`）をアプリケーションコンテナと共有して、ベアラーSVIDがノードのディスクに書き込まれないようにします。ホストからSPIRE Agentソケットをサイドカーにマウントし、共有ボリュームを両方のコンテナの`/var/run/secrets/anthropic.com`にマウントし、アプリケーションコンテナに`ANTHROPIC_IDENTITY_TOKEN_FILE=/var/run/secrets/anthropic.com/token`を設定します。VMやベアメタルでは、spiffe-helperをワークロードと並ぶシステムサービスとして実行し、両者を共有ディレクトリに向けてください。

## Anthropicを構成する

Claude Consoleで[Workload identity](https://platform.claude.com/settings/workload-identity-federation)ページ（`platform.claude.com/settings/workload-identity-federation`）に移動し、**Connect workload**をクリックして、**Custom OIDC**を選択します。ウィザードが、発行者の登録、サービスアカウントの作成、フェデレーションルールの作成を順に案内します。

ウィザードがこれらのリソースを作成します。ウィザードに入力する場合でも、[Admin API](https://platform.claude.com/docs/ja/manage-claude/wif-admin-api)に送信する場合でも、以下の値を使用してください。

**フェデレーション発行者：** OIDC Discovery Providerの公開URLを`discovery`モードで登録します。AnthropicはこのURLから`/.well-known/openid-configuration`を取得し、返された`jwks_uri`をたどってトラストドメインの署名鍵を取得します。

```json
{
  "name": "spire-prod",
  "issuer_url": "https://oidc-discovery.prod.example.com",
  "jwks": { "type": "discovery" }
}
```

ディスカバリープロバイダーがパブリックインターネットから到達できない場合は、JWKSを自分で取得し（`curl https://oidc-discovery.prod.example.com/keys`）、返された`keys`配列の内容を使用して`"jwks": {"type": "inline", "keys": [...]}`で発行者を登録してください。`inline`モードでは、`issuer_url`はJWT-SVIDの`iss`クレームと比較されるだけです。Anthropicがそこに到達しようとすることはありません。

<Warning>
  SPIREはJWT署名鍵を頻繁にローテーションします。デフォルトではCAと同じ周期（`ca_ttl`、24時間）です。ディスカバリーURLの代わりにインラインJWKSで発行者を登録する場合、SPIREがローテーションするたびにJWKSを更新する必要があります。ワークロードが新しい鍵を提示し始める前にその鍵を追加し、古い鍵で署名されたトークンの有効期限が切れたら**置き換えられた鍵を削除**してください。インラインJWKSに残された古い鍵は無期限に信頼され続けます。
</Warning>

公開ディスカバリーエンドポイントを公開せずにJWKSの更新を自動化するには、SPIRE Serverの[BundlePublisher](https://spiffe.io/docs/latest/deploying/spire_server/#built-in-plugins)プラグイン（`aws_s3`、`gcp_cloudstorage`、または`k8s_configmap`）を`format = "jwks"`で構成して、ローテーションのたびにJWT署名鍵を外部ストレージにプッシュし、[Admin API](https://platform.claude.com/docs/ja/manage-claude/wif-admin-api#federation-issuers)を通じて発行者のインライン鍵を更新してください。

**フェデレーションルール：** JWT-SVIDの`sub`（SPIFFE ID）と、spiffe-helperにリクエストするよう構成した`aud`に一致させます。SPIFFE IDはURI文字列であり、`subject_prefix`はそれらを不透明なテキストとして照合するため、完全一致の値でも末尾`*`のプレフィックス一致でも機能します。より複雑なパターンにはCELの`condition`を使用してください。

```json
{
  "name": "spire-inference-worker",
  "issuer_id": "fdis_...",
  "match": {
    "subject_prefix": "spiffe://prod.example.com/ns/inference/sa/worker",
    "audience": "https://api.anthropic.com"
  },
  "target": {
    "type": "service_account",
    "service_account_id": "svac_..."
  },
  "workspace_id": "wrkspc_...",
  "oauth_scope": "workspace:developer",
  "token_lifetime_seconds": 600
}
```

`token_lifetime_seconds`は、交換によって返されるAnthropicアクセストークンの有効期間であり、JWT-SVIDの有効期間ではありません。SDKはアクセストークンを自動的に更新します。

ワークロードが許す限り具体的にしてください。`subject_prefix`を`spiffe://prod.example.com/ns/inference/*`に緩めるのは、そのパス配下に登録されたすべてのワークロードが同じAnthropicサービスアカウントにマッピングされるべき場合のみにしてください。ルールの`fdrl_...` IDをワークロードの`ANTHROPIC_FEDERATION_RULE_ID`環境変数に追加します。

## トークンを取得して使用する

Claude SDKは、spiffe-helperが管理するファイルからJWT-SVIDを読み取るか、Javaを除き、トークンプロバイダーを通じてSPIFFE Workload APIを直接呼び出すことができます。ファイル方式は最もシンプルな統合方法で、すべてのSDK言語で機能します。トークンプロバイダー方式はサイドカーが不要になりますが、アプリケーションの言語でSPIFFE Workload APIクライアントが必要です。

<Tabs>
  <Tab title="spiffe-helperによるファイルベース">
    spiffe-helperが新しいJWT-SVIDを`/var/run/secrets/anthropic.com/token`に書き込むように構成したら、`ANTHROPIC_IDENTITY_TOKEN_FILE`にそのパスを設定します。あわせて、`ANTHROPIC_FEDERATION_RULE_ID`、`ANTHROPIC_ORGANIZATION_ID`、`ANTHROPIC_SERVICE_ACCOUNT_ID`、`ANTHROPIC_WORKSPACE_ID`も設定します。SDKはトークン交換のたびにファイルを読み取るため、常に最新のローテーション済みSVIDを使用します。また、Anthropicアクセストークンの有効期限が切れる前に、トークンを自動的に更新します。各値の取得元については、[環境変数](https://platform.claude.com/docs/ja/manage-claude/wif-reference#environment-variables)を参照してください。

    <CodeGroup>
      ```bash cURL
      JWT=$(cat "$ANTHROPIC_IDENTITY_TOKEN_FILE")

      ACCESS_TOKEN=$(curl -sS https://api.anthropic.com/v1/oauth/token \
        -H "content-type: application/json" \
        --data @- <<JSON | jq -r .access_token
      {
        "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
        "assertion": "$JWT",
        "federation_rule_id": "$ANTHROPIC_FEDERATION_RULE_ID",
        "organization_id": "$ANTHROPIC_ORGANIZATION_ID",
        "service_account_id": "$ANTHROPIC_SERVICE_ACCOUNT_ID",
        "workspace_id": "$ANTHROPIC_WORKSPACE_ID"
      }
      JSON
      )

      curl https://api.anthropic.com/v1/messages \
        -H "authorization: Bearer $ACCESS_TOKEN" \
        -H "anthropic-version: 2023-06-01" \
        -H "content-type: application/json" \
        -d '{
          "model": "claude-opus-5-5",
          "max_tokens": 1024,
          "messages": [{"role": "user", "content": "Hello, Claude"}]
        }' | jq -r '.content[] | select(.type == "text") | .text'
      ```

      ```bash CLI
      # spiffe-helper が次のファイルに書き込む JWT-SVID を読み取ります:
      # ANTHROPIC_IDENTITY_TOKEN_FILE。加えて ANTHROPIC_FEDERATION_RULE_ID、
      # ANTHROPIC_ORGANIZATION_ID、ANTHROPIC_SERVICE_ACCOUNT_ID、ANTHROPIC_WORKSPACE_ID も読み取ります。
      ant messages create \
        --model claude-opus-5-5 \
        --max-tokens 1024 \
        --message '{role: user, content: "Hello, Claude"}'
      ```

      ```python Python
      import anthropic

      # spiffe-helper が次のファイルに書き込む JWT-SVID を読み取ります:
      # ANTHROPIC_IDENTITY_TOKEN_FILE。あわせて ANTHROPIC_FEDERATION_RULE_ID、
      # ANTHROPIC_ORGANIZATION_ID、ANTHROPIC_SERVICE_ACCOUNT_ID、ANTHROPIC_WORKSPACE_ID も読み取ります。
      client = anthropic.Anthropic()

      message = client.messages.create(
          model="claude-opus-5-5",
          max_tokens=1024,
          messages=[{"role": "user", "content": "Hello, Claude"}],
      )
      print(next(block.text for block in message.content if block.type == "text"))
      ```

      ```typescript TypeScript
      import Anthropic from "@anthropic-ai/sdk";

      // spiffe-helper が書き込む JWT-SVID（書き込み先:
      // ANTHROPIC_IDENTITY_TOKEN_FILE）に加え、ANTHROPIC_FEDERATION_RULE_ID、
      // ANTHROPIC_ORGANIZATION_ID、ANTHROPIC_SERVICE_ACCOUNT_ID、ANTHROPIC_WORKSPACE_ID を読み取ります。
      const client = new Anthropic();

      const message = await client.messages.create({
        model: "claude-opus-5-5",
        max_tokens: 1024,
        messages: [{ role: "user", content: "Hello, Claude" }]
      });
      for (const block of message.content) {
        if (block.type === "text") {
          console.log(block.text);
        }
      }
      ```

      ```csharp C#
      // spiffe-helper が書き込む JWT-SVID（書き込み先:
      // ANTHROPIC_IDENTITY_TOKEN_FILE）と、ANTHROPIC_FEDERATION_RULE_ID、
      // ANTHROPIC_ORGANIZATION_ID、ANTHROPIC_SERVICE_ACCOUNT_ID、ANTHROPIC_WORKSPACE_ID を読み取ります。
      using var client = new AnthropicClient();

      var message = await client.Messages.Create(new()
      {
          Model = Model.ClaudeOpus5_5,
          MaxTokens = 1024,
          Messages = [new() { Role = Role.User, Content = "Hello, Claude" }],
      });
      foreach (var block in message.Content)
      {
          if (block.Value is TextBlock textBlock)
          {
              Console.WriteLine(textBlock.Text);
          }
      }
      ```

      ```go Go
      // spiffe-helper が書き込む JWT-SVID（書き込み先:
      // ANTHROPIC_IDENTITY_TOKEN_FILE）に加え、ANTHROPIC_FEDERATION_RULE_ID、
      // ANTHROPIC_ORGANIZATION_ID、ANTHROPIC_SERVICE_ACCOUNT_ID、ANTHROPIC_WORKSPACE_ID を読み取ります。
      client := anthropic.NewClient()

      message, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
      	Model:     anthropic.ModelClaudeOpus5_5,
      	MaxTokens: 1024,
      	Messages: []anthropic.MessageParam{
      		anthropic.NewUserMessage(anthropic.NewTextBlock("Hello, Claude")),
      	},
      })
      if err != nil {
      	panic(err)
      }
      for _, block := range message.Content {
      	if textBlock, ok := block.AsAny().(anthropic.TextBlock); ok {
      		fmt.Println(textBlock.Text)
      		break
      	}
      }
      ```

      ```java Java
      // spiffe-helper が次のファイルに書き込む JWT-SVID を読み取ります:
      // ANTHROPIC_IDENTITY_TOKEN_FILE。あわせて ANTHROPIC_FEDERATION_RULE_ID、
      // ANTHROPIC_ORGANIZATION_ID、ANTHROPIC_SERVICE_ACCOUNT_ID、ANTHROPIC_WORKSPACE_ID も読み取ります。
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      var message = client.messages().create(MessageCreateParams.builder()
              .model(Model.CLAUDE_OPUS_5_5)
              .maxTokens(1024)
              .addUserMessage("Hello, Claude")
              .build());

      IO.println(message.content());
      ```

      ```php PHP
      use Anthropic\Client;

      // spiffe-helper が次の書き込み先に出力する JWT-SVID を読み取ります:
      // ANTHROPIC_IDENTITY_TOKEN_FILE。あわせて ANTHROPIC_FEDERATION_RULE_ID、
      // ANTHROPIC_ORGANIZATION_ID、ANTHROPIC_SERVICE_ACCOUNT_ID、ANTHROPIC_WORKSPACE_ID も読み取ります。
      $client = new Client();

      $message = $client->messages->create(
          model: 'claude-opus-5-5',
          maxTokens: 1024,
          messages: [['role' => 'user', 'content' => 'Hello, Claude']],
      );
      $textBlock = array_find($message->content, static fn ($block): bool => $block->type === 'text');
      echo $textBlock->text, PHP_EOL;
      ```

      ```ruby Ruby
      require "anthropic"

      # spiffe-helper が次のファイルに書き込む JWT-SVID を読み取ります:
      # ANTHROPIC_IDENTITY_TOKEN_FILE。あわせて ANTHROPIC_FEDERATION_RULE_ID、
      # ANTHROPIC_ORGANIZATION_ID、ANTHROPIC_SERVICE_ACCOUNT_ID、ANTHROPIC_WORKSPACE_ID も読み取ります。
      client = Anthropic::Client.new

      message = client.messages.create(
        model: "claude-opus-5-5",
        max_tokens: 1024,
        messages: [{role: "user", content: "Hello, Claude"}]
      )
      puts message.content.find { it.type == :text }.text
      ```
    </CodeGroup>
  </Tab>

  <Tab title="SPIFFE Workload APIを介したトークンプロバイダー">
    Javaを除き、SPIFFE Workload APIクライアントを直接組み込んだワークロードでは、spiffe-helperを使用する必要はありません。代わりに、エージェントソケットから新しいJWT-SVIDを取得するトークンプロバイダーをSDKに渡します。SDKはトークン交換のたびに事前にプロバイダーを呼び出すため、ワークロードは常に有効期限内のSVIDを提示します。成熟したWorkload APIクライアントがあるのは、Python（[py-spiffe](https://github.com/HewlettPackard/py-spiffe)）とGo（[go-spiffe](https://github.com/spiffe/go-spiffe)）です。

    <CodeGroup exclude="shell, typescript, java, csharp, php, ruby">
      ```python Python
      import os
      import anthropic
      from anthropic import WorkloadIdentityCredentials
      from spiffe import JwtSource

      AUDIENCE = "https://api.anthropic.com"

      # SPIFFE_ENDPOINT_SOCKET にある SPIRE Agent のソケットに接続します。
      jwt_source = JwtSource()


      def fetch_jwt_svid() -> str:
          svid = jwt_source.fetch_svid(audience={AUDIENCE})  # audience is a set of strings
          return svid.token


      client = anthropic.Anthropic(
          credentials=WorkloadIdentityCredentials(
              identity_token_provider=fetch_jwt_svid,
              federation_rule_id=os.environ["ANTHROPIC_FEDERATION_RULE_ID"],
              organization_id=os.environ["ANTHROPIC_ORGANIZATION_ID"],
              service_account_id=os.environ["ANTHROPIC_SERVICE_ACCOUNT_ID"],
              workspace_id=os.environ.get("ANTHROPIC_WORKSPACE_ID"),
          ),
      )

      message = client.messages.create(
          model="claude-opus-5-5",
          max_tokens=1024,
          messages=[{"role": "user", "content": "Hello, Claude"}],
      )
      print(next(block.text for block in message.content if block.type == "text"))
      ```

      ```go Go
      import (
      	"context"
      	"fmt"
      	"os"

      	"github.com/anthropics/anthropic-sdk-go"
      	"github.com/anthropics/anthropic-sdk-go/option"
      	"github.com/spiffe/go-spiffe/v2/svid/jwtsvid"
      	"github.com/spiffe/go-spiffe/v2/workloadapi"
      )
      // ...
      	const audience = "https://api.anthropic.com"

      	ctx := context.Background()
      	source, err := workloadapi.NewJWTSource(ctx)
      	if err != nil {
      		panic(err)
      	}
      	defer source.Close()

      	fetchJWTSVID := func(ctx context.Context) (string, error) {
      		svid, err := source.FetchJWTSVID(ctx, jwtsvid.Params{Audience: audience})
      		if err != nil {
      			return "", err
      		}
      		return svid.Marshal(), nil
      	}

      	client := anthropic.NewClient(
      		option.WithFederationTokenProvider(fetchJWTSVID, option.FederationOptions{
      			FederationRuleID: os.Getenv("ANTHROPIC_FEDERATION_RULE_ID"),
      			OrganizationID:   os.Getenv("ANTHROPIC_ORGANIZATION_ID"),
      			ServiceAccountID: os.Getenv("ANTHROPIC_SERVICE_ACCOUNT_ID"),
      			WorkspaceID:      os.Getenv("ANTHROPIC_WORKSPACE_ID"),
      		}),
      	)

      	message, err := client.Messages.New(ctx, anthropic.MessageNewParams{
      		Model:     anthropic.ModelClaudeOpus5_5,
      		MaxTokens: 1024,
      		Messages: []anthropic.MessageParam{
      			anthropic.NewUserMessage(anthropic.NewTextBlock("Hello, Claude")),
      		},
      	})
      	if err != nil {
      		panic(err)
      	}
      	for _, block := range message.Content {
      		if textBlock, ok := block.AsAny().(anthropic.TextBlock); ok {
      			fmt.Println(textBlock.Text)
      			break
      		}
      	}
      ```
    </CodeGroup>

    <Note>
      その他の言語では、ランタイムのSPIFFE Workload APIクライアントでJWT-SVIDを取得します（または、シェルから`spire-agent api fetch jwt`を実行します）。取得したJWT-SVIDをファイルに書き込み、ファイルベースのタブと同様に、`ANTHROPIC_IDENTITY_TOKEN_FILE`にそのパスを設定してください。
    </Note>
  </Tab>
</Tabs>

## セットアップを検証する

SDKを組み込む前に、SPIRE Agentから直接JWT-SVIDを取得し、クレームがフェデレーションルールの期待と一致することを確認してください。別のSPIFFE実装を使用している場合は、そのCLIまたはWorkload APIクライアントでJWT-SVIDを取得し、同じ方法でペイロードをデコードしてください。

<Note>
  Workload APIは呼び出し元プロセスをアテストします。Kubernetes登録エントリの場合、エントリのセレクターを満たし、エージェントソケットがマウントされているポッド内でこのコマンドを実行してください（例えば`kubectl exec`を使用）。VMやベアメタルでは、エントリの`unix:`セレクターに一致するユーザーまたはプロセスとして実行してください。アテストされていないホストシェルから実行すると`no identity issued`が返されます。これは検証ステップで最もよくある失敗です。
</Note>

```bash CLI
spire-agent api fetch jwt \
    -audience https://api.anthropic.com \
    -socketPath /run/spire/sockets/agent.sock \
    -output json \
  | jq -r '.[0].svids[0].svid' \
  | jq -rR 'split(".")[1] | gsub("-";"+") | gsub("_";"/") | @base64d | fromjson'
```

`-output json`フラグはSVIDレスポンスとバンドルレスポンスを2要素のJSON配列として返すため、`jq -r '.[0].svids[0].svid'`で素のトークンを抽出できます。`-output`のない古いSPIREバージョンでは、コマンドは代わりにラベル付きのブロックを出力します。その場合は、デフォルトの出力を`awk '/^[[:space:]]*eyJ/{print $1; exit}'`にパイプしてトークン行を抽出してください。`iss`が登録したOIDC Discovery ProviderのURLであること、`sub`がワークロードのSPIFFE IDであること、`aud`に`https://api.anthropic.com`が含まれていることを確認してください。次に、[トークンを取得して使用する](https://platform.claude.com/docs/ja/manage-claude/wif-providers/spiffe#acquire-and-use-the-token)のcURLの例を実行します。交換が成功すると、`sk-ant-oat01-`で始まる`access_token`が返されます。交換が不透明な`401` `authentication_error`レスポンス（メッセージ`Authentication failed`）で失敗した場合は、Claude Consoleの[認証履歴ページ](https://platform.claude.com/settings/workload-identity-federation?tab=history)で拒否理由を確認し、[失敗した交換のトラブルシューティング](https://platform.claude.com/docs/ja/manage-claude/wif-reference#troubleshoot-a-failed-exchange)を参照してください。SPIRE側で最もよくある原因は、SPIRE Serverの`jwt_issuer`とフェデレーション発行者として登録されたURLの不一致です。

## ルールのスコープを設定する

SPIFFE IDのパス規約は運用者が定義するものであるため、フェデレーションルールの`subject_prefix`マッチャーは登録エントリが使用するパススキームを反映する必要があります。一般的なスキームには、`spiffe://<trust-domain>/ns/<namespace>/sa/<service-account>`（spire-controller-managerの`ClusterSPIFFEID`リソースがデフォルトで発行する形式）や、VMおよびベアメタルワークロード向けの`spiffe://<trust-domain>/host/<hostname>/<service>`があります。

<Warning>
  `subject_prefix`が`spiffe://prod.example.com/*`の場合、トラストドメイン内のすべてのワークロードに一致します。`audience`マッチャーがなければ、ルールは任意のオーディエンス向けに発行されたJWT-SVIDも受け付けてしまい、ワークロードが無関係なリライングパーティ向けにリクエストしたものも含まれます。
</Warning>

ルールの`match`ブロックを、ユースケースに適合する最も狭いスコープに固定してください。

* **1つのワークロードに固定する：** `subject_prefix`を末尾の`*`なしの完全なSPIFFE IDに設定します。
* **常にオーディエンスを設定する：** ルールで`audience`を必須とし、spiffe-helper（またはWorkload API呼び出し）を同じ値で構成して、他のリライングパーティ向けに発行されたSVIDが拒否されるようにします。
* **パスセグメントでスコープを設定する：** `spiffe://prod.example.com/ns/inference/*`を使用して名前空間配下に登録されたすべてのワークロードに権限を付与し、1つのルールを広げるのではなく、名前空間ごとに別々のルールとAnthropicサービスアカウントを作成します。
* **トラストドメインごとに1つの発行者：** 各SPIREトラストドメインには独自の署名鍵とOIDC Discovery Providerがあります。それぞれを別々のフェデレーション発行者として登録し、ルールを、そのルールが一致するSPIFFE IDを所有する発行者にバインドしてください。

## 次のステップ

<CardGroup cols={2}>
  <Card title="OktaでWIFを使用する" icon="lock" href="https://platform.claude.com/docs/ja/manage-claude/wif-providers/okta">
    Workload Identity Federationを使用して、OktaサービスアプリケーションのアイデンティティをClaude APIにフェデレーションします。
  </Card>

  <Card title="Workload Identity Federation" icon="cloud" href="https://platform.claude.com/docs/ja/manage-claude/workload-identity-federation">
    長期間有効な静的APIキーの代わりに、独自のアイデンティティプロバイダーから取得した短期間有効なアイデンティティトークンでワークロードをClaude APIに対して認証します。
  </Card>

  <Card title="WIFリファレンス" icon="book" href="https://platform.claude.com/docs/ja/manage-claude/wif-reference">
    Workload Identity Federationの環境変数、検証ルール、プロファイル構成、エラーリファレンス。
  </Card>

  <Card title="KubernetesでWIFを使用する" icon="cube" href="https://platform.claude.com/docs/ja/manage-claude/wif-providers/kubernetes">
    projected service accountトークンを使用して、セルフマネージドKubernetesクラスターからClaude APIに対して認証します。
  </Card>
</CardGroup>
