🦘

バイパスを禁止し、CloudFrontだけを経由してApp Runnerへのアクセスを許可する方法

2024/05/12に公開

こんにちは!@Ryo54388667です!☺️

普段は都内でエンジニアとして業務をしてます!
主にTypeScriptやNext.jsといった技術を触っています。

今回はAWS App Runnerへの直アクセスを禁止し、CloudFrontを経由してアクセスのみ許可する方法を紹介していきます!

📌 やりたいこと

アプリのソースのあるオリジンサーバーとCDNを設定すると、CDN経由でオリジンにアクセスすることが可能になりますが、CDNを経由せず、直接オリジンサーバーにアクセスすることも可能です(バイパス)。今回はオリジンをAWS App Runner とし、CDNにCloudFront を利用してバイパスさせないようにしてみます。

メリットとしては、CDN経由が保証されれば、レスポンス速度の向上やサーバー負荷の軽減はもちろんですし、CDNにWAFの設定することもできます。設定しておいて損はないのかなと思います。ただ、余分なコストはかかりますが、そこは仕方がないですね😅

📌 方法

自分が思いつくのは下記の2つの方法でした!

  1. セキュリティグループによるアクセス制御(ネットワーク層)
  2. 特定のヘッダーによる制御(アプリケーション層)

セキュリティグループによるアクセス制御 (ネットワーク層)

大枠としては、以下のような手順です。

  1. CloudFrontのIPアドレスのみ許可するようなセキュリティグループを作成する
  2. 任意のVPCとサブネットを作成する
  3. 「受信ネットワークトラフィック」でプライベートエンドポイントを選択し、作成しておいたVPC、サブネット、セキュリティグループを設定する

2と3については、下記のクラメソさんの記事が非常にわかりやすかったです!
https://dev.classmethod.jp/articles/aws-app-runner-supports-privately-accessible-services-amazon-vpc/

ここでは、1について補足しておきます。
始めに、この制御を考えたとき、「CloudFrontのアウトバウンドIPを制御すればいいかー」と思って調べたのですが、下記を見てギョッとしました。これを全部ぽちぽち設定するの面倒だなと。。。
CloudFrontエッジサーバーの場所とIPアドレス範囲

でもシンプルな制御方法がありました!これを解決してくれるものがCloudFrontマネージドプレフィックスリストです。

セキュリティグループのインバウンドルールにマネージドプレフィックスリストがあるので、そちらを設定します。これを作成後は2.3に移り、設定できれば完了です。

特定のヘッダーによる制御 (アプリケーション層)

大枠としては、以下のような手順です。

  1. CloudFrontでカスタムヘッダーを追加
  2. アプリのソース内で評価する

まず、1についてですが、CloudFrontのカスタムヘッダーに特定のヘッダーを追加してください。なるべく推測されにくいものを設定することをおすすめします。

あとは、自分の環境では、「オリジンリクエストポリシー - オプション」を「なし」にしないとカスタムヘッダーが転送されませんでした😇より良い設定があれば教えていただきたいところです。

2については利用している言語、フレームワークの仕様に合わせて設定してください。
今回はNext.jsを利用したケースを例示します。middleware.tsで設定するのが良いかと思います。

// src/middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  console.log('middleware.ts')
  const customHeaderValue = request.headers.get(CUSTOM_HEADER_KEY_NAME);
  console.log("@@@@ カスタムヘッダー @@@ : ", customHeaderValue)
  if (customHeaderValue !== CUSTOM_HEADER_VALUE) {
     return NextResponse.redirect(new URL('/403', request.url))
  }
  return NextResponse.next()
}

export const config = {
   matcher: '/hogehoge',
}

参考:middleware

App Runnerのアプリケーションログを見ると、意図通りカスタムヘッダーが転送されていることがわかります。

📌 まとめ

  1. セキュリティグループによるアクセス制御(ネットワーク層)
  2. 特定のヘッダーによる制御(アプリケーション層)

より良い方法があれば教えてください〜

最後まで読んでいただきありがとうございます!
気ままにつぶやいているので、気軽にフォローをお願いします!🥺
https://twitter.com/Ryo54388667/status/1733434994016862256

Discussion