こんにちは!日々の開発やインフラの管理、本当にお疲れ様です。
新しいシステムを作ったり、APIを公開したりするとき、「動くものができた!」という瞬間は本当に嬉しいものですよね。でも、その裏で「セキュリティの設定って、これで本当に大丈夫なのだろうか…?」と、ちょっと不安になることはありませんか?
特に、WebフロントエンドとAPIサーバーを切り離して開発する現代のシステムでは、避けて通れないのが「CORS(クロスオリジンリソースシェアリング)」という仕組みです。
「名前からして難しそう…」と感じるかもしれませんが、大丈夫です!今回は、身近な「家の鍵と訪問者」の防犯にたとえながら、CORSの仕組みと、API Gatewayで絶対にやってはいけない設定、そして私たちが取るべき正しい対策について、一歩ずつ優しく紐解いていきましょう。
—
1. なぜCORSが必要なの? 〜泥棒から家を守る「インターホン」のたとえ〜
私たちが普段使っているWebブラウザは、実はとてもお節介で、かつ心配性な警備員のような存在です。
例えば、あなたが「A銀行の口座ページ」を開いているとします。その状態で、全く関係のない怪しい「Bサイト」にアクセスしたとします。もし、その怪しいBサイトが、あなたのブラウザにこっそり命令して「A銀行のAPIにアクセスして、預金残高を取ってこい!」と裏で指示できたらどうなるでしょうか?
…想像しただけでゾッとしますよね。銀行の口座情報が勝手に盗み見られてしまいます。
これを防ぐためにブラウザに備わっているルールが「同一同一生成元ポリシー(Same-Origin Policy)」です。基本的には、「自分が今いる場所(オリジン)と違う場所にあるサーバーとは、勝手に通信しちゃダメ!」という厳格な決まりになっています。
じゃあ、なぜCORS(お墨付き)が必要なの?
とはいえ、現代のWebは、フロントエンド(ReactやVue.jsなど)を https://app.example.com で動かし、APIは別のサーバー https://api.example.com からデータを取得するという形が主流です。これでは、ブラウザの警備員が厳しすぎて、正当な通信までストップしてしまいます。
そこで登場するのが CORS(Cross-Origin Resource Sharing) です。
これは、APIサーバー側がブラウザに対して、
「あ、このフロントエンド(https://app.example.com)からのアクセスなら、私の家に入ってきてもいいよ!特別に許可するね!」
と、いわば「公式の招待状(許可証)」を渡してあげる仕組みなんです。
—
2. 攻撃者が狙う盲点!「誰でもウェルカム」が招く悲劇
ここで、今回の本題である「API Gatewayにおける設定ミス」の話をします。
開発初期や、テストを早く終わらせたいとき、「CORSエラーが面倒くさいから、とりあえず全部許可しちゃえ!」ということで、以下のような設定をしてしまうことがあります。
Access-Control-Allow-Origin: *(どこから来ても許可!)
この *(アスタリスク)は、すべての場所からのアクセスを無条件で受け入れる「ワイルドカード」と呼ばれる設定です。
家の防犯にたとえるなら、「我が家の玄関の鍵は常に全開です!どこの誰が来ても、リビングに入ってきて自由にとって行ってください!」と看板を掲げているようなものです。泥棒からしたら、こんなにウェルカムな状態はありませんよね。
この設定を放っておくと、悪意あるサイトがあなたのAPIを悪用し、ユーザーのブラウザを踏み台にして不正なデータを書き換えたり、機密情報を盗み出したりするクロスサイト攻撃のターゲットになってしまいます。
—
3. プリフライトリクエストってなに? 〜本番の前の「下見」〜
API GatewayやWebサーバーのログを見ていると、データを取りに行く前に、なんだか見慣れない通信が飛んできていることに気づくかもしれません。
それが「プリフライトリクエスト(Preflight Request)」です。
これは、ブラウザが本番の危なっかしい通信(データの書き換えや、特別なヘッダーを伴う通信など)を行う前に、APIサーバーへこっそり投げる「事前確認の通信(下見)」のことです。HTTPメソッドでいうと、OPTIONS というメソッドが使われます。
[ブラウザ] ── (OPTIONSメソッド:今から〇〇してもいい?) ──> [API Gateway]
[ブラウザ] <── (OK!許可するよ、メソッドはこれね) ──────── [API Gateway]
[ブラウザ] ── (本番の通信:データを送るよ!) ─────────────> [API Gateway]
API Gatewayの設計・運用においてはこのプリフライトリクエストを正しく制御し、必要最小限の許可だけを返すことが、セキュリティを保つ上で非常に重要になります。
—
4. 【実践】API Gatewayでの厳格なCORS設定手順
それでは、実務で私たちがどのようにAPI Gatewayを設定すべきか、具体的なアプローチを見ていきましょう。
ここでは、特定のオリジンのみを許可し、メソッドやヘッダーを厳しく絞り込む設定の考え方を解説します。
① ワイルドカード(*)を絶対にやめる
まずは、すべてのアクセスを許可する * を排除します。自社のフロントエンドが稼働するドメイン名(オリジン)を明確に指定しましょう。
② 許可するHTTPメソッドを最小化する
APIが実際に必要とするメソッド(例: GET や POST のみ)に限定します。何でもかんでも PUT や DELETE を許可しないのが鉄則です。
③ 許可するカスタムヘッダーを制限する
認証トークンなどをやり取りするために Authorization ヘッダーや Content-Type ヘッダーを使うことが多いですが、これも必要なものだけに絞り込みます。
—
設定のコード・構成イメージ(JSON形式の例)
多くのクラウドサービス(AWS API Gatewayなど)やリバースプロキシのCORS設定では、以下のようなポリシーや設定ファイルを記述します。実務でそのまま参考にできるサンプルを見てみましょう。
{
"corsConfiguration": {
// 許可するオリジン(「*」は使わず、自社アプリのドメインを厳密に指定する)
"allowOrigins": [
"https://app.example.com",
"https://admin.example.com"
],
// 許可するHTTPメソッド(本当に必要なものだけに絞る)
"allowMethods": [
"GET",
"POST",
"OPTIONS"
],
// 許可するHTTPヘッダー(認証に必要な最小限のヘッダーを指定)
"allowHeaders": [
"Content-Type",
"Authorization",
"X-Requested-With"
],
// 許可するレスポンスヘッダー(必要に応じてクライアントに公開するもの)
"exposeHeaders": [
"X-Total-Count"
],
// プリフライトリクエストの結果をブラウザにキャッシュする時間(秒)
// 無駄なOPTIONSリクエストを減らしてパフォーマンスを向上させる
"maxAge": 600,
// 認証情報(CookieやAuthorizationヘッダーなど)の送信を許可するかどうか
"allowCredentials": true
}
}
この設定のポイントは、「誰から(Origins)」「どんな手段で(Methods)」「何を渡すのか(Headers)」を、必要最小限(最小権限の原則)に絞り込んでいる点です。これだけで、セキュリティリスクは劇的に低下します。
—
まとめ:一歩ずつ、堅牢なAPIへ
今回は、API GatewayにおけるCORS設定の厳格化とプリフライトリクエストの仕組みについて、防犯のたとえを交えながら解説しました。
- CORSは、ブラウザという警備員に見せる「公式の招待状」である。
Access-Control-Allow-Origin: *というワイルドカードは、家の鍵を全開にするようなものなので絶対に避ける。- プリフライトリクエスト(
OPTIONS)を活用し、許可するメソッドやヘッダーは最小限に絞り込む。
セキュリティ対策と聞くと難しく身構えてしまうかもしれませんが、「誰にどこまで許可するべきか」を一つずつ整理していけば、決して越えられない壁ではありません。
明日の開発やインフラ設定の際には、ぜひあなたのAPI GatewayのCORS設定をそっと見直してみてくださいね。「一歩ずつ、安全なシステムを一緒に作っていきましょう!」
コメント