プラットフォーム チームに Claude Code をデプロイします。 Anthropic の Workload Identity フェデレーションを構成して、すべてのセッションが証明済みの OIDC アサーションを有効期間の短いトークンと交換するようにします。セキュリティ レビューはクリーンです。静的キー、セッションごとの ID、有効期限切れのトークンはありません。翌朝、あるエンジニアは、スクリプトで必要なため、シェル プロファイルに export ANTHROPIC_API_KEY=sk-ant-... を追加します。フェデレーションは、エンジニアが実行するすべてのセッションでサイレントにバイパスされるようになりました。エラー、警告、ログエントリはありません。静的キーが優先され、証明されたパスは決して呼び出されません。
これは理論上の競合状態ではありません。これは、Anthropic の文書化された認証情報の解決順序であり、フェデレーションの展開が静かに失敗する最も一般的な方法です。
静的キーの問題
Claude Code を認証するデフォルトの方法は、静的 API キー、つまり sk-ant- 文字列を ANTHROPIC_API_KEY として設定することです。これは機能しますが、エンタープライズ ID 管理と競合する 3 つの特性があります。
有効期限なし、ローテーション信号なし。 静的キーは、誰かが取り消すまで有効です。組み込みの有効期間、ローテーション リマインダー、再認証を強制するメカニズムはありません。概念実証中に発行されたキーは、数か月後も本番ワークロードを認証できます。
共有 ID。 同じキーを使用するすべてのセッションは、同じプリンシパルとして認証されます。監査証跡には、どのワークスペースが使用されたかが示されますが、どのエンジニア、どのマシン、またはどのオートメーションが特定のリクエストを実行したかを区別することはできません。セッションごとのアトリビューションは構造的に不可能です。
連邦よりも黙って優先されます。 これはフットガンです。 Anthropic の資格情報解決では、静的キー (ANTHROPIC_API_KEY、層 2) がフェデレーション パス (層 4) の上に配置されます。両方が同じ環境に存在する場合、静的キーが優先されます。フェデレーション交換は決して試行されません。エラーは発生しません。ワークロードは静的キーの ID の下で正常に実行され、フェデレーションに基づいて構築されたすべてのガバナンスの前提 (セッション スコープの ID、証明されたアサーション、トークンの有効期限) がサイレントに無効になります。
空の変数 (ANTHROPIC_API_KEY="") であっても、その優先スロットを占有します。認証は失敗しますが、ランタイムがフェデレーション パスに到達することは妨げられます。失敗モードは「認証エラー」であり、「フェデレーションへの失敗」ではありません。
Workload Identity フェデレーションの仕組み
WIF は静的キーを交換に置き換えます。検証されたアサーションが入力され、有効期間の短いトークンが出力されます。アサーションは JWT です。SPIFFE ID プロバイダーからの JWT-SVID、または Anthropic 組織が信頼する発行者からの標準 OIDC トークンのいずれかです。
交換は RFC 7523 (JWT ベアラーグラント) に従います。ワークロードは、どのフェデレーション ルールと照合するか (fdrl_)、どのサービス アカウントとして機能するか (svac_)、交換がどの組織に属するかという 3 つの識別子とともにアサーションを Anthropic のトークン エンドポイントに提示します。コードでは、交換の中心は JSON 本文を含む POST です。
type exchangeRequest struct {
GrantType string `json:"grant_type"` // "urn:ietf:params:oauth:grant-type:jwt-bearer"
Assertion string `json:"assertion"` // 検証済みの JWT-SVID または OIDC トークン
FederationRuleID string `json:"federation_rule_id"` // fdrl_...
OrganizationID string `json:"organization_id"`
ServiceAccountID string `json:"service_account_id"` // svac_...
WorkspaceID string `json:"workspace_id,omitempty"`
}
応答は RFC 6749 トークン応答です。作成されたトークンには、sk-ant-oat プレフィックス (OAT = OAuth アクセス トークン)、宣言されたスコープ (完全な非管理 API アクセスの場合は workspace:developer、または MCP トンネル管理の場合は org:manage_tunnels)、および 60 秒から 24 時間の有効期間が含まれます。
リフレッシュトークンはありません。作成されたトークンの有効期限が切れると、ワークロードはそのアサーションを再提示し、交換を再度実行する必要があります。これは意図的なものです。アサーション自体が証明されている (SPIFFE ワークロード API または OIDC プロバイダーによってアップストリームで検証されている) ため、すべての再交換が再証明となります。侵害されたトークンは、残りの有効期間内のみ有効であり、攻撃者がそれを延長するために悪用できる更新パスはありません。
その結果、セッションごとの ID が得られます。各 Claude Code セッションは、独自のアサーションを交換し、独自の短命トークンを受け取り、個別のプリンシパルとして認証します。監査証跡には、どのサービス アカウントが動作し、どのフェデレーション ルールにバインドされ、どのワークスペースにスコープが設定されたかが記録されます。
static-key-shadows-federation フットガンの検出
WIF を展開するだけでは十分ではありません。また、環境内の何かがそれをサイレントにバイパスしたことを検出する必要もあります。コネクタは、静的資格情報 (ANTHROPIC_API_KEY または ANTHROPIC_AUTH_TOKEN) の存在についてランタイム環境を検査し、(宣言されたフェデレーション ルールまたは ANTHROPIC_IDENTITY_TOKEN_FILE シグナルを通じて) フェデレーションが同時に使用されているかどうかを確認します。両方の条件が真の場合、重大度の高いガバナンス結果が生成されます。
func (s *Source) detectShadowing(at time.Time) (model.FindingReport, bool) {
_, hasKey := s.envLookup(envAPIKey)
_, hasAuth := s.envLookup(envAuthToken)
if !hasKey && !hasAuth {
return model.FindingReport{}, false
}
_, hasTokenFile := s.envLookup(envIdentityTokenFile)
federationInUse := len(s.federation) > 0 || hasTokenFile
if !federationInUse {
return model.FindingReport{}, false
}
// ...
return model.FindingReport{
Kind: "governance",
Severity: model.SeverityHigh,
Title: "Static Anthropic key shadows Workload Identity Federation",
// DetailHash は、どの変数が優先されるかを識別する — 値は記録しない
}, true
}
調査結果の詳細ハッシュは、キーの値を埋め込むことなく、どの 静的変数が存在するか、および どの フェデレーション シグナルをシャドウするかを記録します。マスクされたフォームさえありません。ハッシュは実行全体にわたって安定しているため、ガバナンス エンジンによって重複が排除され、SIEM はケースに応じてクエリを実行できます。
フェデレーションが使用されていない静的キーは単なる静的キーであり、コネクタはそれにフラグを立てません。この結果は、両方が存在する場合にのみ実行されます。これは、オペレーターがフェデレーションがアクティブであると信じているのに実際はそうではない特定の構成であるためです。
調整ループ: 宣言されたものと実際のもの
静的キーのフットガンを検出できれば、半分は終わります。残りの半分は、フェデレーション構成自体がドリフトしていないことを確認します。コネクタは、宣言されたベースライン (オペレーターが管理対象として明示的に宣言したフェデレーション ルール) を維持し、それを Anthropic 組織の WIF 構成のライブ状態と比較します。
ライブ状態は、3 つの WIF Admin API エンドポイントから取得されます。
GET /v1/organizations/service_accounts— フェデレーション ルールの対象となるサービス アカウント (svac_)GET /v1/organizations/federation_issuers— 組織が信頼する OIDC/SPIFFE 発行者 (fdis_)GET /v1/organizations/federation_rules— 発行者をサービス アカウントにバインドするルール (fdrl_)
これらのエンドポイントには、org:admin OAuth ベアラー トークンが必要です。これは、名簿読み取りで使用される sk-ant-admin Admin API キーとは別の認証情報です。 WIF 管理 API は管理 API キーを明示的に拒否します。そのため、コネクタは調整に別の認証されたクライアントを使用します。
宣言されたものとライブのものの差分により、次の 7 つのカテゴリの結果が生成されます。
| ドリフトケース | それが何を意味するか | 重大度 |
|---|---|---|
undeclared_live_rule | オペレータが宣言したり管理したりしていない実際のルール | 高 |
declared_rule_not_live | 上流に存在しない宣言されたルール | 中 |
scope_drift | ライブスコープが宣言されたスコープから分岐しました | 中 (組織全体に拡大した場合は高) |
lifetime_drift | ライブトークンの有効期間が宣言されたものと異なる | 中 (宣言より長い場合は高) |
over_broad_subject | 実際のサブジェクト制約のないライブ ルール | 中 |
orphan_rule | 欠落している発行者またはサービス アカウントを参照するルール | 中 |
orphan_issuer | ルールによって参照されない発行者 | 低い |
2 つのケースは自動的に高重大度にエスカレーションされます。1 つはオペレータが宣言していない組織全体または管理スコープに拡大されたライブ スコープ、もう 1 つは管理されたベースラインよりも長いライブ トークンの有効期間です。どちらも、オペレーターが承認した範囲を超えて爆発範囲を広げます。スコープの正規化 (トリム、重複排除、並べ替え) により、空白や順序の違いによる誤検知を防止します。
org:admin トークンが構成されていない場合、調整パスは実行されません。コネクタは宣言されたのみのベースラインで動作し、そのカバレッジについて誠実です。つまり、ライブ名簿を作成することはありません。ライブ API にアクセスできない場合 (ネットワーク エラー、トークンの有効期限切れ)、単一の reconciliation_unavailable 検出結果が生成され、続行されます。名簿の許可とフットガンの検出は、org:admin トークンの健全性と関連付けられてはなりません。
リードファーストかつ最小限のデータ
コネクタは、厳格なデータ最小化契約に従います。すべての API 呼び出しは GET です。 Anthropic オブジェクトを作成、更新、削除することはありません。 ID、名前、電子メール、役割、重要なヒントなどのアイデンティティ メタデータのみを保持します。決して重要な秘密ではありません。決して秘密鍵ではありません。静止状態でトークンが鋳造されることはありません。
WIF 交換から生成されたトークンは呼び出し元に返され、コネクタによってログに記録されたり、永続化されたり、発行されたりすることはありません。ガバナンス台帳に到達する唯一のレコードは、ExchangeAudit 構造体です。これには意図的にトークンが含まれていません。
type ExchangeAudit struct {
FederationRuleID string
OrganizationID string
ServiceAccountID string
WorkspaceID string
Scope string
TokenType string
ExpiresAt time.Time
}
同じ最小化がライブ調整にも適用されます。コネクタがフェデレーション発行者の JWKS 構成を読み取るとき、検出モード (discovery、explicit_url、または inline) とカスタム CA 証明書が固定されているかどうかという 2 つのブール値に対する応答が減ります。インライン JWK マテリアル (公開キーですが、かさばり、ガバナンスの決定には決して必要ありません) は、保存フィールドまたは出力フィールドにデコードされることはありません。 CA 証明書 PEM は存在フラグを取得するためだけにデコードされ、すぐに破棄されます。
フェデレーション ルールの CEL 条件は、ポスチャ分析のために伝えられますが (ルールの CEL 式はセキュリティ境界の一部です)、評価されることはありません。コネクタには CEL エンジンへの依存関係はありません。評価は別の問題です。
これにより何が可能になるか
静的キーは認証と ID を混同します。すべてのセッションは同じプリンシパルであり、すべてのトークンは永久に存続し、ドットファイルにキーが存在すると、保護されていると思われていたフェデレーションが暗黙的に無効になります。
WIF は 2 つを分離します。認証は、ワークロードが主張する本人であることを証明する、証明されたアサーションによって行われます。 ID のスコープはセッションに限定されます。つまり、有効期間の短いトークン、特定のサービス アカウント、特定のワークスペース、宣言されたスコープです。トークンの有効期限が切れると、ワークロードは再認証されます。構成が変動すると、調整ループにより gap が表面化します。静的キーがメカニズム全体をシャドウする場合、コネクタはそれを検出し、インシデントの発見となる前に報告します。
その結果、資格情報の有効期限が切れ、セッションが帰属可能となり、誰かが意図した状態だけでなく、組織の実際の状態に対してガバナンスの前提が継続的に検証される ID モデルが生まれます。
ID コネクタ、WIF 交換、およびフットガン検出は、アイデンティティ ガバナンス モジュール の一部です。台帳、アクセス マップ、読み取り優先コレクション アーキテクチャなど、より広範なセキュリティ モデルについては、セキュリティ を参照してください。