見出し画像

Cloudflare PagesでホスティングしてIP制限ありでSPAを公開してみた

はじめに

こんにちは、SHIFTの開発部門に所属している Katayama です。

Firebase でアプリケーションを開発していたので hosting には Firebase Hosting を、と考えていたが Firebase Hosting ではアクセス制御をする事はできず、すべてのユーザーが Hosting されたサイトにアクセスできてしまう(いわゆる WAF の機能が Firebase Hosting にはない)。

そこでCloudflare Pagesを利用して SPA をホスティングし、アクセス制御を設けるという事をやってみた。

※前提として今回は GitHub と連携した。全体を図示すると以下のようなイメージになる(Firebase で開発していたのでその部分も図示している。また、今回の構成では全部無料枠内で収めることができた。)。

執筆者プロフィール:Katayama Yuta
認証認可(SHIFTアカウント)や課金決済のプラットフォーム開発に従事。リードエンジニア。 経歴としては、SaaS ERPパッケージベンダーにて開発を2年経験。 SHIFTでは、GUIテストの自動化やUnitテストの実装などテスト関係の案件に従事したり、DevOpsの一環でCICD導入支援をする案件にも従事。その後現在のプラットフォーム開発に参画。

Cloudflare Pagesでホスティングする

Cloudflare の Pages にアクセスし、「プロジェクトを作成」からプロジェクトを作成する。

GitHub に接続を行うと、GitHub 上で Cloudflare Pages への認可をする画面が開くので認可を行う。

認可を行うと Cloudflare Pages の設定画面に戻るので設定を続ける。

ホスティングするものがどのディレクトリに生成されるか?などの設定を行う。

※上記の Firebase 関連の環境変数はフロントエンドのビルドに利用するもの= Web でサイトを開けば確認できるもの、なのでマスキングする意味は本質的にはないが、今回は検証目的でもあるので敢えてマスキングしている。

「保存してデプロイする」をクリックすると、自動でデプロイが開始され、最終的に以下のような成功のログが出れば、実際に自分のアプリを開けるようになる。

デプロイ後のドメインは以下の画像の緑枠の部分から確認できる。

これで Cloudflare Pages での SPA のホスティングが完了になる。続いてアクセス制御に関する設定を行っていく。

Deploy a Vite 3 siteにあるように、Node.js のバージョンはNODE_VERSIONの環境変数で指定する事ができる。何も指定しないとv12.18.0になってしまう(さすがに古すぎると思うが・・・)。

アクセス制限を設ける

詳細は以下で見ていくが、最終的には以下のような形で自身のWebサイトを保護することができる。

 1. https://hoeghoge.pages.dev にアクセス
 2. Cloudflare Zero Trustの画面(以下)にリダイレクトする

 3. 認証(Google or メールへの一時コード送信)を行う
 4. 認証の結果、Zero TrustのPolicyルールに合致するアクセスであれば、https://hoeghoge.pages.dev にリダイレクトする
もし、アクセス許可がない人のアクセスであれば、以下のようにForbiddenの画面になる

プレビュー環境へのアクセスを制限する

Cloudflare Pages にはデプロイするブランチによってプレビュー環境かプロダクションかを設定する機能がある。まずは、プレビュー環境へのアクセスを制限する方法を見ていく。

設定は簡単で、以下のように「Access ポリシー」を設定するセクションがあるので、それを有効にするだけ。有効にすると以下のようにドメインに対してポリシーが適用される。

このポリシーによりプレビュー環境の URL を開いても、いきなりサイトが開くのではなく、Cloudflare Zero Trust の認証画面が開くようになる。

ここにログインするアカウントのメアドを入力すると、そのメアドに一時コードが届くのでそれを入力する事でプレビュー環境を開けるようになる(メアドに Cloudflare Access のポリシーに未設定のメアドを入力しても一時コードは届かないので、プレビュー環境の閲覧者を制限できる)。

※上記ではメアドでの認証をしていたが、設定画面でIdentity providersによる認証にする事も可能。そのためにはまず、「Cloudflare Zero Trust > Settings > Authentication > Login methods」で追加したい認証方法を追加する必要がある。

今回は Google アカウントでログインで Cloudflare Zero Trust の認証ができるようにしてみる。手順は以下の画面に詳細に書かれているので、その通りに設定していけばいい(Google の OAuth2.0(OpenID Connect)を利用する際には、必ずOAuth 同意画面の設定が求められるので行う必要があるが、今回の Cloudflare Zero Trust での認証時の Google でログインする操作の認可リクエストは"response_type=code"の"scope=email profile openid"なので認可画面は開かない= OAuth 同意画面が開かないので、本来はしなくてもいい設定にはなるが、Google の制約上仕方なく設定が必要になる)。

設定が完了すると、以下のように Google が「Login methods」に追加されるので、「Test」から Google でのログインで認証ができているか?を検証できる。

上記の「Test」から Google でのログインがうまくいく= OAuth2.0 の設定に問題がなければ以下のように Cloudflare Zero Trust の画面にリダイレクトする。

ここまで設定が完了すると、以下のように「Cloudflare Access / Applications」の Authentication に Google が表示されるようになる。これを有効にする。

そしてプレビュー環境の URL を開くと、以下のような Cloudflare Zero Trust の画面にリダイレクトし、そこに Google での認証が追加されている事が確認できる。

※上記の設定で必要になるteam domainについては、「Cloudflare Zero Trust > Settings > General」から確認できる。

Cloudflare Access の設定を確認する

上記の手順でプレビュー環境へのアクセス制限を実現できたが、どうしてアクセス制限ができていたか?の詳細を少し確認しておく。

以下の「ポリシーを管理する」からCloudflare Access(Cloudflare Zero Trust)の画面に遷移する。

「Access / Applications」を開くと、Cloudflare Pages でデプロイしたサイトに対するアクセスルールが設定されている事が確認できる。

表示されている「Application name」をクリックして表示されるサイドバーの「Configure」をクリックすると、以下のように設定を確認できる画面が開く。

そこに表示されている「Allow Members - Cloudflare Pages」の「Configure」を確認すると"Include"の"Emails"にメアドが指定されているのが確認できる。この設定により上記の「プレビュー環境へのアクセスを制限する」が実現できていた。

※Include の意味などはRule typesに詳細が書かれているが、概要としては以下のように整理される。

  • Include OR 論理演算子に似ています。複数のインクルードルールが指定されている場合、ユーザーはそのうちの 1 つの条件のみを満たす必要があります。

  • Exclude NOT 論理演算子のように動作します。除外条件を満たすユーザーは、アプリケーションへのアクセスを許可されません。

  • Require AND 論理演算子のように機能します。ユーザがアクセスを許可されるには、指定されたすべての Require ルールを満たす必要があります。

※ちなみに、一番最初に Cloudflare Access にアクセスした場合は、以下の画像のように「Choose a plan」の画面になるので案内に従ってプラン(Free)を選択し、支払方法を設定していく必要がある(Free でも支払方法自体は必須になる模様)。

プロダクション環境へのアクセスを制限する

プロダクション環境の制限を IP アドレスで行う事で、限られた IP からの接続でのみサイトを開けるようにする、という事をやってみる。設定は簡単で、以下のようにPoliciesでIP Rangeを指定するだけ。

これで上記の IP に合致しない IP からの接続は拒否できる。拒否された場合は以下のようなアクセス制限がされた事を示す画面(403 Forbidden)が表示される=サイトへのアクセスを IP アドレスで制限されている事が確認できる。

※1 点注意として、上記のようにActionsAllowにすると、Cloudflare Accessのサービスの仕組み上、認証情報を利用しないポリシーでも必ず認証画面が開いてしまう。それが煩わしい場合には、Bypassに設定し、Cloudflare Access での保護(認証)を行わないという設定もできる。

まとめとして

今回は Cloudflare Pages と Cloudflare Zero Trust(Access)を利用して、自身のサイトへのアクセスを制御するという事をやってみた。開発途中のものだったり、特定のメンバーだけにしかサイトを公開しないなどをする際には、Cloudflare Pages と Cloudflare Zero Trust を利用する事で簡単にそれが実現できる(しかも無料枠で)。今後 PoC 開発などではこういう方法で簡単にアクセス制御をするのも選択肢の 1 つだと感じた。

また、アプリケーションコードにアクセス制御に関わる実装を一切しなくていいのもメリットだと感じた(通常のアプリケーション側で必要なユーザー認証でのデータへのアクセス制御ではなく、Webサイトそのものへのアクセスの意味)。

※ちなみに、Firebase Authentication で認証を実現している場合、Cloudflare Pages のドメインと、認証画面に表示されるドメイン(Firebase デフォルトのドメイン)がずれるという事が起きる。

これを回避したい場合、Google ログインのリダイレクト ドメインのカスタマイズにあるように自分が持つカスタムドメインを利用する必要がある。Cloudflare Pages のドメイン pages.dev の DNS 管理はユーザ側ではできないので、Firebase のカスタム ドメインを接続するを完了できない(pages.dev に TXT レコードなどを追加できないので pages.dev を Firebase のカスタムドメインに設定するのは不可)。

《この公式ブロガーの記事一覧》


お問合せはお気軽に
https://service.shiftinc.jp/contact/

SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/

SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/

SHIFTの導入事例
https://service.shiftinc.jp/case/

お役立ち資料はこちら
https://service.shiftinc.jp/resources/

SHIFTの採用情報はこちら 
https://recruit.shiftinc.jp/career/


みんなにも読んでほしいですか?

オススメした記事はフォロワーのタイムラインに表示されます!