【Claude Code 連載 第50回】gateway.yaml 完全ガイド — Claude アプリゲートウェイ設定リファレンス

スポンサーリンク
【Claude Code 連載 第50回】gateway.yaml 完全ガイド — Claude アプリゲートウェイ設定リファレンス 用語解説
【Claude Code 連載 第50回】gateway.yaml 完全ガイド — Claude アプリゲートウェイ設定リファレンス
この記事は約32分で読めます。
よっしー
よっしー

こんにちは。よっしーです(^^)

スポンサーリンク

背景

この連載では、Claude Codeの公式ドキュメントを1ページずつ読み解いていきます。公式ドキュメントは情報が網羅されている分、「結局どの機能を、どんな場面で使えばいいのか」は自分で考える必要があり、読むのに意外と時間がかかります。そこで、私が実務で使うために読み込んだ内容を「使う場面→実例コード」の順に整理して残していくことにしました。専門家の解説というより、一次情報を読んだ記録です。推測や動作を確認していない部分には、その都度そう書きます。

1. 一言でいうと何か

gateway.yaml は、Claude アプリゲートウェイの挙動をすべて決める1枚の YAML ファイルです。

前回(第49回)はゲートウェイを立ち上げるところまでを扱いました。今回はその設定ファイルの中身です。このファイルが定義するのは4つ——どこでリッスンするか、開発者がどうサインインするか、推論がどこへ行くか、どんなポリシーとテレメトリが適用されるか

読み込みのタイミングと検証の仕方に、運用上ありがたい性質があります。ゲートウェイは claude gateway --config /path/to/gateway.yaml起動時に1回だけ読み込み、すべてのオプションをブート時にスキーマ検証します。つまり形式が誤った設定は、最初の使用時ではなく起動時にフィールドレベルのエラーで落ちます。さらに不明なキーはブート失敗を引き起こすので、タイプミスが「黙って無視された設定」ではなく「名前付きのエラー」として出ます。設定ファイルの世界では、これはかなり親切な設計です。

構造は必須5セクション+オプション6セクション

必須は listen(バインドアドレス・パブリック URL・TLS)、oidc(IdP と、誰がサインインできるか)、session(発行するベアラートークン)、store(PostgreSQL)、upstreams(推論の行き先)。

オプションは admin(Admin API と支出制限)、enforcement(支出制限のフェイル動作)、modelsauto_include_builtin_models(モデルカタログとアップストリームごとの ID)、managed(IdP グループ別のポリシー)、telemetry(OTLP 転送)、そして access_control / limits / timeouts / rate_limits(HTTP チューニング)。省略したセクションはデフォルトが使われます。

2. どういう場面で役立つか

シーン1:チームごとにモデルと権限を出し分ける

managed.policies の中核用途です。業務委託メンバーには Haiku だけ、社員には Opus まで。ウェブ系ツールは委託には禁止。こうした区別を IdP グループで書き分けられます。availableModels はサーバー側(/v1/messages)でも強制されるので、クライアントを改造しても抜けられません。

シーン2:プロビジョニングスループットを使い切ってからオンデマンドに流す

同じプロバイダーのアップストリームを複数並べ、モデルごとに行き先を変えられます。PT 枠を先に消費し、429 で自動的にオンデマンドへ、それも駄目なら別アカウント、最後は Anthropic API へ——といった段階的フェイルオーバーが YAML だけで組めます。

シーン3:US 以外のリージョンや Foundry を使う

models: ブロックが必須になるケースが3つ明記されています——US 以外の Amazon Bedrock リージョン、Bedrock のプロビジョニングスループット ARN、Microsoft Foundry のデプロイメント名。特に Foundry は正規モデル ID ではなく管理者が付けたデプロイメント名を使うので、マッピングを書かないと動きません。

シーン4:開発者ごとのコストを可視化する

telemetry.forward_to を設定すると、CLI が OTLP でゲートウェイに送り、ゲートウェイが各宛先へリレーします。CLI は各エクスポートに認証済みユーザーのアイデンティティ(user.id / user.email / user.groups)をスタンプするので、開発者側の設定なしでユーザー別のコスト按分ができます。

不要・向かないケース

  • グループごとに MCP サーバーを配りたい。できません。ポリシーの cli ブロック内の mcpServersゲートウェイのブートで拒否されます。各デバイスにファイルベースの managed-mcp.json を置くか、開発者にローカルで追加させてください。
  • SCIM でユーザーを同期したい。ゲートウェイは独自のユーザーディレクトリを持ちません。リクエストごとに IdP トークンから認可し、トークンの groups クレームでポリシーを評価するだけです。列挙すべき名簿がないので SCIM エンドポイントも存在しません。ライフサイクル管理は IdP 側で行い、Claude アカウント自体の SCIM が必要なら Claude for Enterprise の機能です。
  • 管理 UI で設定したい。ありません。YAML を編集して再デプロイします。
  • 新しい Claude Code の設定キーをすぐポリシーに入れたい。検証はゲートウェイにバンドルされたスキーマで行われるため、新リリースで増えたトップレベルキーを使うには先にゲートウェイをアップグレードする必要があります。
  • gateway.yaml にシークレットを直書きしたい。やめてください(次節)。

3. 設定の実例と解説

大前提:シークレットは展開参照で書く

client_secretjwt_secretpostgres_url などを YAML に直書きしてはいけません。2つの参照形式があり、ブート時に解決されます。

形式解決先用途
${VAR}環境変数 VAR未定義ならブート失敗コンテナ環境変数、env インジェクション経由の AWS Secrets Manager
${file:/path}ファイルの内容(トリミング済み)Kubernetes Secret ボリュームマウント、Vault Agent、SOPS

未定義でブート失敗する挙動は重要です。シークレットが渡っていないのに起動してしまうという最悪のパターンを防いでくれます。

必須セクション(1)listen

host(デフォルト 0.0.0.0)と port(デフォルト 8080)は素直です。要注意なのは public_url

これは外部から見える https:// オリジンで、IdP の redirect_uri と検出メタデータを組み立てるのに使われます。ALB / Ingress / Cloud Run など TLS 終端プロキシの背後では必須です。理由が明快で——**ゲートウェイは自分のオリジンを組み立てるとき X-Forwarded-* ヘッダーを信頼しません。クライアントがスプーフできるからです。**加えて、テレメトリを有効にする場合も必須。この URL からクライアントに配る OTLP エンドポイントを構築するためです。

tls.cert / tls.key はゲートウェイ自身が TLS を終端する場合の PEM パス。trusted_proxies はロードバランサーの CIDR で、設定するとそのピアからの X-Forwarded-For だけを信頼して実クライアント IP を記録します(nginx の set_real_ip_from 相当)。public_url とは役割が別で、こちらは IP ごとのレート制限と監査のためのものです。

必須セクション(2)oidc

このブロックはフィールドが17個あります。ここでは実務で最初に触るものだけ扱い、残りは公式参照に回します。

issuer は OIDC 検出のベース。/.well-known/openid-configuration を提供する必要があります。http:// 発行者も受け付けますが、http://localhost:8081 のようなループバック発行者は SSRF ガードで拒否され、CLAUDE_GATEWAY_ALLOW_LOOPBACK=1 を環境に設定した場合のみ通ります。

client_id / client_secret は OAuth クライアント登録から。

allowed_email_domainsemail クレームが指定ドメインにない id_token を拒否します(大文字小文字を区別しない)。マルチテナント IdP の設定ミスに対する多層防御です。なおこの設定と無関係に、email_verified が明示的に falseid_token は常に拒否されます。

allowed_groups はサインインを特定の IdP グループのメンバーに限定します。許可メールドメイン内でもグループに属さなければ拒否されます。

groups_claim(デフォルト groups)と email_claim(デフォルト email)は、IdP がクレームを別名で出す場合に使います。実例が具体的で助かります——Microsoft Entra はアプリロールを roles の下に発行し、ADFS や Entra B2C は upnpreferred_username を発行することがあります。どちらもフラットキーのほか RFC 6901 の JSON ポインタ/resource_access/gateway/roles のようなネスト)を受け付け、email_claimフォールバックキーのリストも受け付けます(最初に存在するものを使用)。

userinfo_fallback(デフォルト false)は、id_token がメールやグループを省略する場合に /userinfo から補完します。Keycloak の軽量アクセストークン、Okta org サーバー、ADFS の最小トークンでは必須id_token が権威的なままで、userinfo は隙間を埋めるだけです。

scopes(デフォルト [openid, profile, email, offline_access])を上書きするときの注意が重い。offline_access を外すとリフレッシュトークンが無効になり、開発者は session.ttl_hours ごとにブラウザログインをやり直すことになります。

Google Workspace は特別扱いが必要です。Google の id_token はグループクレームを含まないため、google_groups で Admin SDK Directory API を叩いてグループを検索します。admin.directory.group.readonly スコープでドメイン全体の委任を持つサービスアカウントキーと、偽装する Workspace 管理者の admin_email が要ります(Directory API は実在の管理者サブジェクトを要求します)。そして各ユーザーのグループ「メールアドレス」がグループクレームになるので、allowed_groupsmanaged.policies.match.groups もグループメールで書くことになります。

そのほか use_pkce(デフォルト true)、clock_skew_seconds(デフォルト 0・厳密。サインイン直後の「トークン期限切れ/まだ有効でない」エラーが出るなら増やす)、token_endpoint_auth_methodid_token_signed_response_alg(デフォルト RS256)、additional_authorized_partiesdiscovery_urlextra_auth_paramsform_action_originsca_cert_pem があります。詳細は公式リファレンスを参照してください。

form_action_origins だけ補足しておくと、これは Chrome がリダイレクトチェーン全体に form-action CSP を強制することへの対処です。Azure AD から ADFS へのフェデレーション、ハブスポーク Okta、企業 SSO インターセプターなど2つ目のホストを経由する構成でハマります。

必須セクション(3)session

jwt_secret32バイト以上のエントロピー(例:openssl rand -base64 32)。HS256 のベアラートークンに署名します。ローテーション用に配列も受け付け、インデックス0が署名、全エントリが検証します。手順は「新しいシークレットを先頭に追加 → ttl_hours 待つ → 古いものを削除」。

ttl_hours(デフォルト 1)はトークンの有効期間です。短いほどプロビジョニング解除が速く反映され、長いほど IdP へのラウンドトリップが減るというトレードオフ。ただし例外があって、offline_access が使えずリフレッシュトークンが発行されない IdP では無言リフレッシュが起きないため、開発者が1時間ごとにブラウザログインへ戻されます。その場合は 812 に上げることが推奨されています。

必須セクション(4)store

postgres_url が必須。役割は明確で、デバイスグラントの集合場所です——ブラウザのコールバックが書き込み、ポーリングする CLI が読む。だからレプリカ間で共有された状態が必要なのです。

DDL の話は前回も触れましたが、対処法がここで具体化されています。ゲートウェイはブート時に自分でマイグレーションを走らせるので、ロールには対象スキーマの CREATE TABLE が要ります。セキュリティポリシーがアプリケーションロールの DDL を禁じている場合は、管理者ロールでマイグレーションを実行し、アプリロールにはゲートウェイのテーブルへの SELECT, INSERT, UPDATE, DELETE を付与します。これは初回だけでなく、新リリースがマイグレーションを出荷するたびに必要です。

max_connections(デフォルト 5)は共有 DB に対して保守的な値。支出制限を有効にするとホットパスが推論リクエストごとに数回の操作を行うので、専用 DB では増やします。ただしレプリカ数 × この値を DB の max_connections 以下に保つこと。

必須セクション(5)upstreams — フェイルオーバーの規則

upstreams順序付きリストです。ゲートウェイは要求されたモデルを解決できる最初のアップストリームに転送します。

フェイルオーバーする条件が明示されています:5xx429401403404、タイムアウト、欠落エンドポイント(501それ以外の 4xx ではフェイルオーバーしません。理由が理にかなっています——これらはリクエストではなくアップストリーム側に起因するから。401 / 403 は「ゲートウェイの認証情報がそのアップストリームで通らなかった」、404 は「そのアップストリームがそのモデルを提供していない」であり、後ろのアップストリームなら提供できるかもしれない

404 でのフェイルオーバーはゲートウェイ v2.1.198 以降。それ以前は、後ろのアップストリームがモデルを持っていても最初の 404 をクライアントに返していました。

同じプロバイダーを複数並べるときは異なる name: が必須です。

認証情報の更新については朗報があります。Bedrock / Claude Platform on AWS / Agent Platform / Foundry のクライアントは起動時に1回構築され、SDK が内部で認証情報をリフレッシュするため、クラウド認証情報のローテーションに再起動は不要です。一方、静的な Anthropic API キーとベアラーは起動時に読み込まれるので、更新にはシークレットの再マウントと再起動が要ります。

最小の Anthropic アップストリームはこれだけです。

upstreams:
  - provider: anthropic
    auth:
      api_key: ${ANTHROPIC_API_KEY}
    # または OAuth ベアラー(例:Workload-Identity-Federation 交換トークン):
    #   oauth_token: ${file:/var/run/secrets/anthropic-oauth-token}
    # base_url: https://api.anthropic.com   # デフォルト;フォワードプロキシの場合はオーバーライド

api_keyx-api-key を、oauth_tokenAuthorization: Bearer を送ります。静的キーもベアラーも避けたい場合は Workload Identity Federation が使え、ワークロードの OIDC JWT をファイルとしてマウントすると、ゲートウェイがそれを短期ベアラーと交換して自動リフレッシュします。トークンファイルは交換のたびに再読み込みされるので、ローテーションに再起動が不要です。

Amazon Bedrock はこう書きます。

upstreams:
  - provider: bedrock
    region: us-east-1
    auth: {}                           # 推奨:AWS デフォルト認証情報チェーン
    # または明示的な認証情報:
    # auth:
    #   aws_access_key_id: ${AWS_AKID}
    #   aws_secret_access_key: ${AWS_SK}
    #   aws_session_token: ${AWS_ST}
    # または Bedrock API ベアラートークン:
    # auth:
    #   aws_bearer_token: ${AWS_BEARER_TOKEN}
    # FIPS または VPC エンドポイントデプロイメント用に bedrock-runtime エンドポイントをオーバーライド:
    # base_url: https://bedrock-runtime-fips.us-east-1.amazonaws.com

空の auth: {} が推奨形です。AWS SDK のデフォルト認証情報チェーン(env vars、~/.aws/credentials、ECS タスクロール、EC2 インスタンスメタデータ、EKS の IRSA)を使い、本番ではゲートウェイの Pod に IAM ロールを付与します。明示的な認証情報を書く場合は完全でなければならずaws_access_key_idaws_secret_access_key が揃っていないとブート時に失敗します(v2.1.207 より前は部分的な auth: が検証を通っていました)。

他のプロバイダーも形は同じで、認証の作法だけ違います。

  • Claude Platform on AWSprovider: anthropicAws):regionworkspace_id が必須。エンドポイントは https://aws-external-anthropic.<region>.api.aws に導出されます。第一者モデル ID を使い、anthropic-beta ヘッダーを尊重し、count_tokens を提供するので、Bedrock 固有の変換は適用されません。Bedrock とは別の AWS アカウントで動き、独自のサービス名 aws-external-anthropic で SigV4 署名するため、Bedrock スコープの IAM ロールでは認可されません。認証は API キーか SigV4 の二択(両方あれば API キーが優先)。Claude Code v2.1.198 以降が必要で、それ以前のゲートウェイはブート時に拒否します。
  • Google Cloud Agent Platformprovider: vertex):regionproject_idauth: {} で Application Default Credentials。サービスアカウント JSON キーはサポートされるが非推奨で、Workload Identity かインスタンスへのサービスアカウント付与が勧められています。region: global を設定するとグローバルエンドポイントが使え、Google が各リクエストを利用可能なリージョンにルーティングするので、リージョンごとのモデル可用性を追わずに済みます。
  • Microsoft Foundryprovider: foundry):resource からエンドポイントを導出。auth: { use_azure_ad: true } が推奨で DefaultAzureCredential を通ります。API キーも使えますがプロジェクト全体に効き、自動ローテーションされません。そして前述のとおり、Foundry はデプロイメント名を使うので models: ブロックが必須です。

各プロバイダーの IAM 権限・モデルアクセス・Kubernetes 連携(IRSA / Workload Identity / AKS ワークロードアイデンティティ)の詳細は公式のセットアップ表を参照してください。

複数アップストリームとモデルルーティング

ここが upstreamsmodels の合わせ技です。

upstreams:
  # プライマリ:ホームリージョンのプロビジョニングスループット。
  - name: bedrock-pt
    provider: bedrock
    region: us-east-1
    auth: {}
  # オーバーフロー:オンデマンドクロスリージョン。
  - name: bedrock-od
    provider: bedrock
    region: us-west-2
    auth: {}
  # 異なるアカウント:想定ロール認証情報経由の別の Bedrock 割り当て。
  - name: bedrock-acct2
    provider: bedrock
    region: us-east-1
    auth:
      aws_access_key_id: ${ACCT2_AKID}
      aws_secret_access_key: ${ACCT2_SK}
  # 最後の手段:直接 Anthropic API。
  - name: anthropic-fallback
    provider: anthropic
    auth:
      api_key: ${ANTHROPIC_API_KEY}
# アップストリームごとのモデル ID はアップストリームの `name:` でキーイングされます。`name:` のないアップストリームはプロバイダー文字列(例:`bedrock`)にデフォルト設定されます。モデルにリストされていないアップストリームはスキップされます。これは、プロビジョニングスループットにモデルをルーティングしながら、他のすべてがオンデマンドのままである方法です。
models:
  - id: claude-opus-4-8
    label: Claude Opus 4.8
    upstream_model:
      bedrock-pt: arn:aws:bedrock:us-east-1:111111111111:provisioned-model/abcdef
      bedrock-od: us.anthropic.claude-opus-4-8
      bedrock-acct2: us.anthropic.claude-opus-4-8
      anthropic-fallback: claude-opus-4-8

肝は**「upstream_model: マップからアップストリームを省くと、そのモデルではそのアップストリームがスキップされる」という規則です。これを使ってモデルスコープのルーティング**ができます——Opus は PT へ、Sonnet と Haiku はオンデマンドへ、といった具合に。429(PT 枠の枯渇)はオンデマンドへ、404(そのアップストリームでモデル未有効)は次のアップストリームへ流れ、解決できないアップストリームはネットワークラウンドトリップなしでスキップされます。

auto_include_builtin_models: true(デフォルト)なら組み込みカタログが使われ、false にすると models: に書いたものだけが公開されます。

ひとつ、技術以外の注意が添えられています。クラウドプロバイダー間や直接 Anthropic API へのフェイルオーバーは、そのリクエストを管理する契約・地域・その他の条件を変えるという点。データレジデンシー要件でゲートウェイを立てている組織にとっては、フェイルオーバー先の選定自体がコンプライアンス判断になります。

なお CLI はどのアップストリームが処理するかに関わらず同じ機能ゲーティングをゲートウェイに適用するので、フェイルオーバーしてもアップストリームが拒否するボディフィールドが送られることはありません。

managed — グループ別ポリシーとマージ規則

ポリシーは順番に評価され、最初にマッチしたものが選ばれます。そして選ばれたポリシーは、match: {} のキャッチオールに「マージ」されます

managed:
  policies:
    # 特定のグループを最初に。
    - match: { groups: [eng-contractors] }
      cli:
        availableModels: [claude-sonnet-4-6]
        permissions: { deny: ["WebFetch", "WebSearch"] }
    # デフォルトキャッチオール最後:認証されたすべてのユーザーにマッチします。
    - match: {}
      cli:
        availableModels: [claude-opus-4-8, claude-sonnet-4-6, claude-haiku-4-5]

マージ規則がキーの種類によって違うのが最重要ポイントです。

  • 許可リストavailableModelspermissions.allow):特定ポリシーのリストが基盤のリストを完全に置き換える
  • 拒否リストとフック配列permissions.denypermissions.askdisabledMcpjsonServersdeniedMcpServersblockedMarketplaces、すべての hooks イベント型配列):基盤との和集合を取る。設計意図が明記されています——組織全体の拒否や監査フックが、ロール別オーバーライドで誤って落ちないようにするため
  • レコード型キーenvmodelOverridesskillOverrides):浅くマージ。ロール別 env は設定したキーだけ上書きし、残りは基盤から継承。

マッチャーは4種類。match: {}(全認証ユーザー)、match: { groups: [...] }大文字小文字を区別、IdP の正確な表記と一致が必要)、match: { email_domain: ... }大文字小文字を区別しない、ポリシーごとに1ドメイン)、両方指定(AND 条件)。

そして落とし穴:どのポリシーにもマッチしない認証ユーザーは「ゲートウェイのデフォルト」を受け取ります——つまりカタログ内の全モデルが使え、管理設定はなし。保証されたデフォルトが欲しければ、必ず最後に match: {} を置いてください

伝播には2つの時計があります。ポリシー内容の変更は次のマネージド設定ポーリングで届き、1時間以内グループメンバーシップの変更はどのポリシーにマッチするかを変えるので、次のセッション再発行(無言リフレッシュ)時に有効になり、session.ttl_hours で上限が決まります。

cli ブロックに何を書くか

cli 値は完全な Claude Code managed-settings.json ドキュメントです。MDM や /etc/claude-code/managed-settings.json で配るのと同じスキーマを、YAML で書いているだけ。

managed:
  policies:
    - match: {}
      cli:
        # モデルアクセス(/v1/messages でサーバー側でも強制)
        availableModels: [claude-opus-4-8, claude-sonnet-4-6, claude-haiku-4-5]
        # 権限ポリシー
        permissions:
          deny:
            - "WebFetch"
            - "Read(./.env)"
            - "Read(./secrets/**)"
          disableBypassPermissionsMode: disable   # --dangerously-skip-permissions をブロック
        allowManagedPermissionRulesOnly: true     # ユーザー/プロジェクト権限ルールを無視
        # CLI プロセスにプッシュされた環境。DISABLE_UPDATES はバックグラウンドと手動更新をブロック;DISABLE_AUTOUPDATER はバックグラウンド更新のみを停止。
        env:
          DISABLE_UPDATES: "1"                    # 独自の配布経由でバージョンをピン
        # 組織全体のフック。フックコマンドはゲートウェイではなく開発者マシンで実行されるため、パスはポリシー内のすべてのクライアント OS に存在する必要があります。
        hooks:
          PostToolUse:
            - matcher: "Edit|Write"
              hooks:
                - { type: command, command: /usr/local/bin/audit-edit.sh }

コメントに書かれている注意が実務的です。フックコマンドはゲートウェイではなく開発者マシンで実行されるので、そのポリシーがマッチする全クライアント OS にパスが存在しなければなりません。macOS と Linux が混在する組織で /usr/local/bin/... を指定するときは要確認です。

強制の主体も整理されています。availableModels だけがゲートウェイ+CLI の両方で強制され、permissions.*allowManagedPermissionRulesOnlyenvhooksCLI が強制します。だからパッチされたクライアントに対して確実なのはモデル許可リストだけ、という理解になります。

検証については、ゲートウェイがブート時に CLI の設定スキーマで各ドキュメントを検証し、認識されないトップレベルキーや不正な値があると、違反キーを全部名指しして起動に失敗します。ただし意図的にオープンな部分があり、envpluginConfigspermissions 配下のネストキーは任意の値を受け付けます(新しいクライアントがゲートウェイの知らないエントリを理解しうるため)。運用としては新しいポリシーを1クライアントでスモークテストしてからロールアウトが推奨されています。

歴史的経緯として、cli キーは以前 settings という名前でした。エイリアスとして今も受け付けられますが、新規は cli を使います。

セキュリティ承認ダイアログ(再訪)

第48回・第49回でも触れた話ですが、このページにはセーフリストの中身が書かれています。

  • セーフリスト上(承認なしで適用):自動更新とモデル名の変数
  • セーフリストにない(承認が必要):プロキシ変数、ベース URL 変数、OTEL_EXPORTER_OTLP_ENDPOINT

つまり telemetry.forward_to を設定すると OTEL_EXPORTER_OTLP_ENDPOINT がプッシュされるので、全インタラクティブクライアントで承認ダイアログが出ます。テレメトリを有効化した日に問い合わせが増える、という事態は予測できるわけです。

このダイアログの意図についての一文が明快です。**「ダイアログは、組織から開発者を保護するのではなく、開発者のマシンを侵害または敵対的なゲートウェイから保護する」。**開発者が拒否すると Claude Code は設定を適用せずに終了します。

他のマネージドソースとの優先順位

デバイスにローカルの managed-settings.json や MDM ポリシーもある場合、マージされません。最優先ソースがすべてのポリシー設定を提供します。順位は上から:

  1. ポリシーヘルパー
  2. ゲートウェイ配信設定
  3. MDM(Windows の HKLM レジストリ / macOS の plist)
  4. managed-settings.json ファイル
  5. HKCU レジストリ(Windows のみ)

例外として、管理者ソースが設定すれば尊重される小さなキー群があります(ユーザー書き込み可能な HKCU 層は除外)——sandbox.network.allowManagedDomainsOnlysandbox.filesystem.allowManagedReadPathsOnly(ロック時は許可リストがソース横断で和集合される)、allowAllClaudeAiMcpssandbox.bwrapPathsandbox.socatPath、そして forceRemoteSettingsRefresh

埋め込みホストは SDK の managedSettings オプションでポリシーを渡せますが、デフォルトでは無視され、マネージドソースが parentSettingsBehavior: "merge" でオプトインした場合のみ適用されます。しかも厳しくはできても緩くはできません

telemetry

telemetry:
  forward_to:
    - url: https://otel-collector.internal.example.com
      headers:
        Authorization: ${OTLP_TOKEN}
      # シグナルごとのオプトイン。デフォルト:メトリクスのみ。
      metrics: true
      logs: false
      traces: false
    - url: https://api.datadoghq.com/api/v2/otlp
      headers:
        DD-API-KEY: ${DD_API_KEY}

シグナルごとに宛先ごとのオプトインで、デフォルトはメトリクスのみ。この既定値には強い理由があります。

  • メトリクス:トークン数、リクエスト数、レイテンシなどの集計カウンター
  • ログとトレース完全な bash コマンド、ツール入力、ファイルパスを含みうる。Claude Code が開発者のマシンで行うことすべてをカバーする

公式の警告どおり、ログとトレースは、アクセス制御と保持ポリシーがそのデータを守れる宛先でのみ有効化すべきです。

有効化すると、ゲートウェイは5つの環境変数を /managed/settings 経由で全接続クライアントにプッシュします:CLAUDE_CODE_ENABLE_TELEMETRY=1OTEL_METRICS_EXPORTER=otlpOTEL_LOGS_EXPORTER=otlpOTEL_TRACES_EXPORTER=otlpOTEL_EXPORTER_OTLP_ENDPOINT=<public_url>。これらはマネージド層で適用されるので、開発者がローカルで設定した OTEL_* を上書きします。

なおトレース(ベータ)には各クライアントで CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1 が追加で必要ですが、ゲートウェイはこの変数をプッシュしないので、マネージドポリシーの env ブロックで配ります。

admin / enforcement(支出制限)

admin ブロックを書くと /v1/organizations/spend_limits が有効になります。認証は3系統——write_keys{id, key} の配列、32文字以上x-api-key で送信、リスト・設定・削除が可能)、read_keys(GET 系のみ)、admin_groups(IdP グループ名。ゲートウェイ JWT だけで完全な管理者アクセス)。使い分けは明快で、人間の管理者にはグループ、マシンには API キー。各キーの id は監査ログに admin-key:<id> として出るので属性可能です。

保持期間のデフォルトは audit_retention_days: 365spend_retention_months: 13(年間比較レポート用に完全な1年+現在の部分月)、identity_retention_days: 90アイデンティティ保持が支出保持より意図的に短いのがポイントで、プロビジョニング解除されたアイデンティティ(PII)は、匿名の支出カウンターが残っている間に期限切れになる設計です。

group_limit_modemin(デフォルト、最も制限的なキャップを適用)か maxblocked_message はブロックされた開発者が見る 429 billing_error に逐語的に追加されるので、申請先の URL や Slack チャネルを書いておくと親切です。

enforcement.fail_closed_on_error(デフォルト false)は、Postgres が落ちたときに推論を止めるかどうか。デフォルトはフェイルオープン(推論は動き続ける)。true にすると上限超過者はブロックされますが、ストアに到達できなければ全員がブロックされます。admin: ブロックがなければ効果はありません。

HTTP チューニング

ブロックキーデフォルト要点
access_controlallow_cidrs / deny_cidrsdeny が先。allow が空でなければデフォルト拒否。/healthz/readyzallow_cidrs の対象外
limitsmax_request_bytes32 MiB超過はバッファリング前に 413。大きな画像やファイルを送るなら増やす
limitsmax_request_header_bytes / max_url_length未設定設定すると 431 / 414
timeoutsupstream_ttfb_ms120000初バイトまでの最大待ち時間。ボディはその後キャップなしでストリーミング。直接 Anthropic パスのみに適用(他はプロバイダー SDK のタイムアウト)
rate_limitsdevice_authorization30 / 600秒IP ごと。共有エグレス IP や NAT 配下の大規模組織では増やす
rate_limitsdevice_verify10 / 600秒/device での user_code 送信

**レート制限はサインインフローにのみ適用され、/v1/messages の推論には適用されません。**混同しやすいので明記されています。

クライアント側の設定(ゲートウェイからは配れない)

ここまでは全部サーバー側です。開発者マシンをゲートウェイに向ける設定は、ゲートウェイからはプッシュできません——それはクライアントに「ゲートウェイがどこにあるか」を教えるものだからです。

{
  "forceLoginMethod": "gateway",
  "forceLoginGatewayUrl": "https://claude-gateway.internal.example.com"
}

配置先は OS ごとに異なります。macOS/Library/Application Support/ClaudeCode/managed-settings.json(または com.anthropic.claudecode マネージド設定ドメイン)。Linux と WSL/etc/claude-code/managed-settings.jsonWindowsC:\Program Files\ClaudeCode\managed-settings.json(または HKLM レジストリ経由のグループポリシー)。通常は MDM で配布します。

再確認ですが、この2キーは管理者制御のマネージド層からのみ尊重され、開発者が自分の ~/.claude/settings.json に書いても効果がありません

なお公式ページ末尾には**全セクションを網羅した「完全な例」**が掲載されています。実際に構築するときは、この記事ではなくそちらをコピー元にしてください(HTTP チューニングはデフォルトのまま残されています)。

4. まとめ + 次回予告

  • gateway.yaml必須5セクション(listen / oidc / session / store / upstreams)+オプション6。起動時に1回読み、スキーマ検証で落ちる不明キーもブート失敗
  • シークレットは ${VAR}${file:/path} で参照する。未定義ならブート失敗するので、渡し忘れて起動する事故が起きない。
  • public_url はプロキシ背後で必須X-Forwarded-* を信頼しない設計だから。テレメトリにも必須。
  • oidc はフィールドが多いが、実務で効くのは userinfo_fallback(Keycloak / Okta org / ADFS で必須)、groups_claim(Entra は roles)、email_claim(ADFS / B2C は upn)、scopes から offline_access を外さないこと、そして Google は google_groups が必要という点。
  • ttl_hours はプロビジョニング解除の速さとログイン頻度のトレードオフ。リフレッシュトークンが出ない IdP では 8〜12 に上げる。
  • upstreams は順序付き。5xx / 429 / 401 / 403 / 404 / タイムアウト / 501 でフェイルオーバー、他の 4xx ではしない404 フェイルオーバーは v2.1.198 以降。
  • models: は US 以外の Bedrock リージョン、PT の ARN、Foundry のデプロイメント名で必須upstream_model: からアップストリームを省くとモデル単位のルーティングになる。
  • managedマージ規則:許可リストは置き換え、拒否リストとフックは和集合、レコード型は浅いマージ。最後に match: {} を置かないと、未マッチのユーザーは全モデル・ポリシーなしになる
  • mcpServers はポリシーに書けない(ブート拒否)。SCIM もない(ユーザーディレクトリを持たないため)。
  • テレメトリのデフォルトはメトリクスのみ。ログとトレースは bash コマンドやファイルパスを含みうるので、宛先を選んでから有効化する。有効化すると全クライアントで承認ダイアログが出る
  • マネージドソースはマージされず、最優先ソースが全部を提供する。ゲートウェイはポリシーヘルパーの次、MDM より上

第49回と合わせると、ゲートウェイの全体像はこうなります。**概要ページで立ち上げ、このリファレンスで作り込む。**そしてまだ残っているのが、本番デプロイと運用の話です。

次回予告(暫定):**デプロイメントガイド(claude-apps-gateway-deploy)**を取り上げ、IdP ごとのセットアップ、コンテナイメージ要件、Kubernetes / Cloud Run へのデプロイ、脅威モデル、アップグレード手順などを扱う予定です。

※連載の実際の次テーマは未確定です。


よっしー
よっしー

何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。

それでは、また明日お会いしましょう(^^)

コメント

タイトルとURLをコピーしました