ブラウザーは同一オリジンポリシーを適用し、ウェブページが同一のプロトコル、ドメイン、ポートのリソースにのみアクセスできるように制限します。https://example.com から https://api.example.com へのリクエストでは、blocked by CORS policy エラーが発生します。特定のクロスオリジンリクエストを許可するには、Nginx Ingress に CORS (Cross-Origin Resource Sharing) のアノテーションを追加します。
仕組み
CORS は 2 種類のリクエストを処理します:単純リクエストとプリフライトリクエストです。
単純リクエスト は、サーバーに直接送信されます:
-
ブラウザーはリクエストに
Originヘッダーを追加します。例:Origin: https://example.com。 -
Nginx Ingress コントローラーは、HTTP メソッドと
Originの値を CORS 設定と照合します。一致する場合、レスポンスにAccess-Control-Allow-Originを追加します。 -
ブラウザーは、
Access-Control-Allow-Originがリクエストのオリジンと一致するかどうかを確認します。一致すれば成功となります。ヘッダーがない場合や、一致しない場合は失敗となります。
プリフライトリクエスト は、本リクエストの前に OPTIONS による確認を送信します:
-
ブラウザーは、実際のリクエスト内容を示す
Access-Control-Request-MethodとAccess-Control-Request-Headersを付けてOPTIONSリクエストを送信します。 -
メソッドまたはヘッダーが許可されていない場合、プリフライトリクエストは失敗し、本リクエストは送信されません。プリフライトリクエストが成功した場合、本リクエストは単純リクエストと同様に処理されます。
次の場合、リクエストはプリフライトをトリガーします:
-
メソッドが
GET、HEAD、POST以外の場合。 -
メソッドが
POSTで、Content-Typeがtext/plain、application/x-www-form-urlencoded、multipart/form-dataのいずれでもない場合。 -
リクエストにカスタムヘッダーが含まれる場合。
cors-allow-credentials が "true" の場合、cors-allow-origin を "*" に設定しないでください。W3C 仕様では、この組み合わせは禁止されています。リクエストに認証情報 (Cookie など) が含まれる場合、サーバーは信頼するオリジンを明示的に指定する必要があります。"*" を使用すると、任意のウェブサイトがユーザーになりすまして認証情報付きのリクエストを送信できるため、セキュリティリスクとなります。
CORS の設定
前提条件
開始する前に、次の項目を満たしていることを確認してください:
-
Nginx Ingress コントローラーがデプロイされている ACK クラスター
-
トラフィックをバックエンドサービスにルーティングする Ingress リソース
-
クラスター内の Ingress リソースを編集する権限
CORS アノテーションの追加
-
ACK コンソールにログインします。左側メニューで、[クラスター] を選択します。
-
[クラスター] ページで対象のクラスターをクリックします。左側メニューで、[ネットワーク] > [Ingress] を選択します。
-
[Ingress] ページで対象の Ingress を見つけ、[操作] 列の [YAMLの編集] をクリックします。
-
シナリオに応じて、
metadata.annotationsに CORS アノテーションを追加します。
シナリオ A:認証情報または Cookie を含むリクエスト (推奨)
フロントエンド (https://example.com または https://app.example.com) からバックエンド API (https://api.example.com) に対して、Cookie や Authorization ヘッダーなどの認証情報を送信する場合に使用します。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-ingress-secure
annotations:
# CORS を有効化します。
nginx.ingress.kubernetes.io/enable-cors: "true"
# Cookie や Authorization ヘッダーなどの認証情報を含むリクエストを許可します。
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
# 正確なオリジンを指定します。認証情報を有効にしている場合は「*」を使用しないでください。
nginx.ingress.kubernetes.io/cors-allow-origin: "https://example.com, https://app.example.com"
# 許可する HTTP メソッドを指定します。
nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, PUT, DELETE, OPTIONS"
# アプリケーションで必要なカスタムヘッダーなど、許可するリクエストヘッダーを指定します。
nginx.ingress.kubernetes.io/cors-allow-headers: "Content-Type, Authorization"
# ブラウザーの JavaScript に公開するカスタムレスポンスヘッダーを指定します。
nginx.ingress.kubernetes.io/cors-expose-headers: "X-Request-ID, Content-Length, Content-Range"
# プリフライトリクエストのキャッシュ期間 (秒) を設定します。86400 は 24 時間です。
nginx.ingress.kubernetes.io/cors-max-age: "86400"
...
シナリオ B:認証情報を含まないリクエスト
認証のない公開の読み取り専用 API に使用します。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-ingress-public
annotations:
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-origin: "*"
# cors-allow-origin が「*」の場合は「false」にする必要があります。
nginx.ingress.kubernetes.io/cors-allow-credentials: "false"
nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, HEAD"
...
CORS 設定の検証
curl を使用して、ブラウザーのプリフライトリクエストをシミュレートします:
curl -i -X OPTIONS 'https://api.example.com/your/path' \
-H 'Origin: https://app.example.com' \
-H 'Access-Control-Request-Method: POST' \
-H 'Access-Control-Request-Headers: Content-Type, Authorization'
プリフライトリクエストが成功すると、2xx のステータスコード (通常は 204 No Content または 200 OK) が返されます:
HTTP/2 204
date: Fri, 12 Sep 2025 03:51:12 GMT
access-control-allow-origin: https://example.com, https://app.example.com
access-control-allow-credentials: true
access-control-allow-methods: GET, POST, PUT, DELETE, OPTIONS
access-control-allow-headers: Content-Type, Authorization
各 access-control-allow-* の値が、Ingress の対応する nginx.ingress.kubernetes.io/cors-* アノテーションの値と一致していることを確認します。
CORS アノテーションのリファレンス
|
アノテーション |
説明 |
HTTP ヘッダー |
例 |
|
|
CORS を有効化または無効化します。 |
N/A |
|
|
|
許可するオリジンです。複数のオリジンは、カンマで区切ります。 |
|
|
|
|
許可する HTTP メソッドです。 |
|
|
|
|
許可するカスタムリクエストヘッダーです。 |
|
|
|
|
Cookie や HTTP 認証などの認証情報を含むリクエストを許可するかどうかを指定します。 |
|
|
|
|
ブラウザーの JavaScript に公開するレスポンスヘッダーです。デフォルトでは、標準ヘッダー ( Nginx Ingress コントローラー v0.44 以降が必要です。 |
|
|
|
|
ブラウザーがプリフライトレスポンスをキャッシュできる最大時間 (秒) です。値を長くするとプリフライトリクエストを削減でき、値を短くするとセキュリティが向上します。 |
|
|
よくある質問
クロスオリジンエラーのトラブルシューティング
ブラウザーの開発者ツールまたは Nginx Ingress コントローラーのログでネットワークリクエストを確認します。リクエストのオリジン、メソッド、ヘッダーが、Ingress の CORS アノテーションと一致していることを確認します。
一般的なエラーメッセージと原因:
-
Method POST is not allowed by Access-Control-Allow-Methods in preflight response— メソッドがcors-allow-methodsに含まれていません。 -
Access to fetch at 'https://api.example.com/data' from origin 'https://app.example.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: xxxx.— プリフライトリクエストが失敗しました。access-control-allow-*レスポンスヘッダーをアノテーションの値と比較してください。
同一ドメイン内のパスごとに異なる CORS ポリシーを設定する方法
CORS アノテーションは Ingress レベルで適用され、パスレベルの設定はサポートされていません。異なるポリシーが必要なパスグループごとに、別々の Ingress リソースを作成してください。例:公開パス用に api-public-ingress.yaml、認証が必要なパス用に api-private-ingress.yaml を作成します。
カスタムレスポンスヘッダーをブラウザーの JavaScript に公開する方法
クロスオリジンのレスポンスでは、ブラウザーからアクセスできるのは、Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma といった標準ヘッダーのみです。X-Request-ID などのカスタムヘッダーは、明示的に公開しない限り JavaScript からは参照できません。
公開するには、アノテーションに cors-expose-headers を追加します。シナリオ A:認証情報または Cookie を含むリクエスト (推奨)を参照してください。
関連ドキュメント
-
Enable CORS — ingress-nginx の公式アノテーションリファレンス