設問と背景
Gateway API v1.5では、HTTPRouteのCORSフィルターがStandardチャネルに移行しました。これにより、ルートのルールで許可されるオリジン、メソッド、リクエストヘッダー、公開ヘッダー(exposed headers)、およびプリフライトのキャッシュ時間を宣言できるようになりました。この設問では、サーバー側の認可や実装固有の検証を維持しながら、適切なゲートウェイ境界にクロスオリジンポリシーを配置できるかがテストされます。
面接官が評価するポイント
面接官は、ブラウザのCORS保護、ゲートウェイのレスポンスヘッダー、そして実際のアイデンティティ認可の区別ができているかを評価します。優れた回答には、OPTIONSプリフライトパス、クレデンシャルとオリジン、ワイルドカードのリスク、ルートごとの最小権限、そしてGateway実装がフィルターをサポートしているかどうかが含まれます。単にallowOrigins: "*"と記述するだけでは、安全な設計を示すことにはなりません。
回答前に明確にすべき質問
どのオリジンとリソースがクロスオリジンアクセスを必要としているか?
本番、プレビュー、管理、およびローカル開発の各オリジンをリストアップし、ドメイン全体ではなくルートごとに認可します。そのリストは監査可能かつ有効期限を設定できるようにし、テスト用のオリジンが本番環境に入らないようにする必要があります。
クレデンシャルは含まれるか?
リクエストがCookie、HTTP認証、またはその他のクレデンシャルを送信するかどうかを確認します。クレデンシャルを含むリクエストには、より厳格なオリジンおよびレスポンスヘッダーのポリシーが必要です。デフォルトで任意のオリジンをクレデンシャルと組み合わせてはなりません。
認可とポリシーのリリースは誰が担当するか?
Gateway、アプリケーション、アイデンティティサービスの責任範囲を明確に定義します。CORSはブラウザのスクリプトがレスポンスを読み取れるかどうかを制御するものであり、トークンの検証、テナントの分離、またはリソースの認可に代わるものではありません。
30秒の回答フレームワーク
「まず、Gateway全体で許可範囲を広げるのではなく、HTTPRouteおよびビジネスリソースごとにオリジンを限定します。各ルートに対してオリジン、メソッド、ヘッダー、公開ヘッダー、maxAgeを指定し、クレデンシャルを伴うルートには審査済みのオリジンと検証済みのレスポンスヘッダーを使用します。OPTIONSプリフライト、実際のリクエスト、エラー、キャッシュの期限切れをテストし、Gateway実装がフィルターをサポートしていることを確認します。最後に、サーバーの認可、監査、ロールバックとは切り離して、ブラウザのアクセス境界としてのCORSを検証します。」
ステップごとの詳細な回答
ステップ1: ルートごとの最小権限を構築する
各HTTPRouteのリソース、オリジン、許可するメソッド、および必要なヘッダーを記録します。1つの寛容なポリシーがドメイン全体に適用されないよう、パブリックな読み取り専用リソースとクレデンシャルを伴うアカウントリソースには別々のルールを使用する必要があります。
ステップ2: フィルターフィールドを設定する
実際の要件に基づいて、allowOrigins、allowMethods、allowHeaders、exposeHeaders、およびmaxAgeを設定します。実装のドキュメントやセキュリティポリシーに照らしてオリジンのパターンをレビューし、不要なワイルドカードよりも明示的なオリジンを優先します。
ステップ3: プリフライトを正しく処理する
ブラウザは、Origin、Access-Control-Request-Method、および場合によってはAccess-Control-Request-Headersを伴うOPTIONSを送信します。Gatewayは、ポリシーと整合性のあるCORSヘッダーを返し、CORSを認識しないバックエンドにプリフライトを転送するのではなく、許可されていないリクエストを明確に拒否する必要があります。
ステップ4: クレデンシャルと認可を分離する
Cookieの属性、CSRF対策、トークン検証、およびサーバーの認可を用いてクレデンシャルの挙動を設計します。ブラウザがスクリプトによるアクセスをブロックしたとしても、サーバー自体がリクエストを認可しなければなりません。
ステップ5: 実装の確認とロールバック
Gatewayコントローラーがv1.5 StandardのCORSフィルターとそのフィールドセマンティクスをサポートしていることを確認します。ブラウザとcurlを使用して、プリフライト、実際のリクエスト、失敗、リダイレクト、キャッシュの挙動を再現します。また、ポリシーの変更、メトリクス、およびロールバックの手順を記録します。
質の高い模範回答
私はHTTPRouteごとにオリジンを限定し、パブリックな検索インターフェースとクレデンシャルを伴うアカウントインターフェースを分離します。各ルールで許可するオリジン、メソッド、リクエストヘッダー、公開ヘッダー、プリフライトのキャッシュ時間を指定し、クレデンシャル付きアクセスには審査済みの本番オリジンのみを使用します。リリース前には、ブラウザでエラー、リダイレクト、キャッシュの期限切れを含むOPTIONSおよび実際のリクエストをテストし、curlとGatewayコントローラーのステータス条件(status conditions)を使用して設定が有効であることを確認します。CORSはブラウザの読み取り境界を定義するだけであり、サーバーは引き続きアイデンティティ、テナント、リソースの認可を実施します。コントローラーのセマンティクスの差異は、アプリケーション層でのフォールバックとともに互換性マトリックスで追跡します。
よくある間違い
- 間違い: グローバルにすべてのオリジンを許可する。 → 失敗の理由: あらゆるルートがブラウザスクリプトから読み取り可能になる可能性があり、監査や取り消しが困難になります。 → 対策: HTTPRouteごとに最小限のオリジンセットを構築します。
- 間違い: 実際のリクエストのみを設定し、OPTIONSを無視する。 → 失敗の理由: 複雑なメソッドやヘッダーは、まずプリフライトによってブロックされます。 → 対策: プリフライトと実際のレスポンスを別々にテストします。
- 間違い: CORSを認可として扱う。 → 失敗の理由: ブラウザ以外のクライアントは依然としてサービスを直接呼び出すことができます。 → 対策: サーバー側でのアイデンティティ、テナント、リソースのチェックを維持します。
- 間違い: コントローラーをテストせずにv1.5のフィールドをリリースする。 → 失敗の理由: 実装によっては、それらを無視、拒否、または異なる解釈をする場合があります。 → 対策: サポートマトリックス、ステータス条件、および実際のトラフィックのリプレイを確認します。
フォローアップ質問と回答
フォローアップ1: アプリケーション内だけでCORSを設定してはいけないのですか?
アプリケーションはリソース固有のポリシーを保持でき、Gatewayはルートレベルのプリフライトおよびサービス間の境界を処理できます。両方の層でヘッダーを設定する場合は、重複や競合を避けるために優先順位を定義してください。
フォローアップ2: maxAgeは常に可能な限り長くすべきですか?
いいえ。プリフライトのキャッシュを長くするとOPTIONSトラフィックは減少しますが、失効の反映が遅れます。変更頻度、リスク、ブラウザの挙動に基づいて選択し、緊急の取り消しに備えてバージョニングされたオリジンまたは短いTTLの経路を確保してください。
フォローアップ3: ワイルドカードオリジンが許容されるのはどのような場合ですか?
クレデンシャルがなく、リスク評価が承認された真にパブリックなリソースの場合のみです。アカウント、管理、テナントのデータには、明示的なオリジンと検証済みのワイルドカード動作を使用する必要があります。
フォローアップ4: 誤って許可されたオリジンをどのように検出しますか?
Origin、ルート、プリフライトの結果、ポリシーのバージョンをログに記録し、オリジンの変更を監査します。許可されたオリジン、不許可のオリジン、期限切れのオリジンから成る自動化マトリックスを実行し、レスポンスヘッダーがポリシーから外れた場合にリリースをブロックします。