Firebase で公開したサイトに IP でアクセス制限をかける
概要
Firebase Hosting で公開した一部のページに特定のIPからのみアクセス可能にしたいという要望を実現したときのメモ。
実装
IP制限をかけたいページへアクセスがあると、Cloud functions の関数を実行し、動的にhtmlを生成して返す。
ほぼほぼこちらの記事通りにした。
今は Hack 的な実装が必要だが、いずれ Firebase 側が対応してくれる気がする。
フォルダ構成(ピックアップ)
├── firebase.json ├── functions │ ├── index.js │ ├── package.json │ └── templates │ ├── 403.html │ ├── foo.html └── public ├── index.html
firebase.json
{ "hosting": { "public": "public", "rewrites": [ { "source": "/foo.html", "function": "ipfilter" } ], "ignore": [ "firebase.json", "**/.*", "**/node_modules/**" ] }, "functions": { "predeploy": [ "npm --prefix \"$RESOURCE_DIR\" run lint" ], "source": "functions" } }
function/index.js
const functions = require('firebase-functions'); const requestIp = require('request-ip'); const ipRangeCheck = require('ip-range-check'); const is = require('is_js'); const fs = require('fs'); const url = require('url'); const allowIps = [ 'xx.xx.xx.xx/xx',// 許可するIPアドレス '127.0.0.1',// ローカル開発環境 ] exports.ipfilter = functions.https.onRequest((request, response) => { // request.headers['x-forwarded-for']に appengine の ip が入っていたため変更した。https://github.com/pbojinov/request-ip/blob/master/src/index.js#L48 const clientIp = is.ip(request.headers['fastly-client-ip']) ? request.headers['fastly-client-ip'] : requestIp.getClientIp(request); let filename = url.parse(request.url).pathname; const isAllowed = ipRangeCheck(clientIp, allowIps); const statusCode = isAllowed ? 200 : 403; if (!isAllowed) { filename = '/403.html'; } const html = fs.readFileSync(`./templates${filename}`).toString(); response.status(statusCode).send(html); });