Using Firebase Hosting, how can I restrict PURGE request to specific IPs

1.1k Views Asked by At

I have a website hosted on Firebase, using static html, no server-side function is used to deliver the result.

When running curl -X PURGE https://mywebsite.com -v -L the result is:

{ "status": "ok", "id": "20755-1619059392-3560756" }

I need a way to restrict this action to specific IPs so that not anybody can reset my cache which might result in extra costs.

Also it seems that Firebase uses Varnish to manage cache (which is something am null at).

My client's security consultant sent us this recommendation on how to handle this issue, I'm not sure exactly if this is .htaccess syntax or what:

# Varnish recommends to using PURGE method only by valid user,
# for example by ip limiting and for other return 405 Not allowed:


acl purge { 
 "localhost";
 "192.168.55.0"/24;
}

sub vcl_recv {
 # allow PURGE from localhost and 192.168.55...
 if (req.method == "PURGE") { 
  if (!client.ip ~ purge) {
   return(synth(405,"Not allowed."));
  }
  return (purge);
 }
}

I don't know how to apply this in Firebase Hosting, again am not using Server Functions, just the regular firebase.json with the following headers:

      "headers": [
        {
          "source": "*.[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].+(css|js)",
          "headers": [
            {
              "key": "Cache-Control",
              "value": "public,max-age=31536000,immutable"
            }
          ]
        },
        {
          "source": "**/*.@(json|eot|otf|ttf|ttc|woff|font.css)",
          "headers": [
            {
              "key": "Access-Control-Allow-Origin",
              "value": "*"
            }
          ]
        }
      ]
3

There are 3 best solutions below

6
On

The following code is VCL code:

acl purge { 
 "localhost";
 "192.168.55.0"/24;
}

sub vcl_recv {
 # allow PURGE from localhost and 192.168.55...
 if (req.method == "PURGE") { 
  if (!client.ip ~ purge) {
   return(synth(405,"Not allowed."));
  }
  return (purge);
 }
}

This code allows you to extend the behavior of Varnish. This code has to be added to your /etc/varnish/default.vcl file.

After adding this code to your VCL file, you have to reload your varnishd process to activate this VCL configuration.

If reloading varnishd is not an option, you can also activate the new VCL file using the following commands:

sudo varnishadm vcl.load purge_acl /etc/varnish/default.vcl
sudo varnishadm vcl.use purge_acl

For more information about Varnish and the VCL programming language, please have look at http://varnish-cache.org/docs/6.0/reference/index.html

0
On

There is no solution for the moment. This is the answer I received from the firebase support :

Hi Damien,

My name is Sergei, thanks for reaching out. I'll be assisting you.

The first thing to be addressed here is the fact that Varnish services fall outside of our scope, so our information about its implementations with our hosting services are not the most abundant.

Unfortunately, right now we can only control the caching behavior with our existing tools.

I am sorry we cannot provide the functionality you need at the time, if you would like to, we can submit the feature request so this is visible to our engineering team.

0
On

If no solution with Firebase Hosting or if Varnish isn't available, maybe try a different solution, for example with a cloud function.

Maybe need to adapt content of "function" configuration part in some cases.

firebase.json (Hosting behavior)

...
 "rewrites": [
   {
     "source": "**/*.@(json|eot|otf|ttf|ttc|woff|font.css)",
     "function": "no_purge"
   }
 ]
...

/functions/index.js (Cloud Function)

const functions = require('firebase-functions');

exports.no_purge = functions.https.onRequest((req, res) => {

 if(req.method == 'PURGE') {    /* complete this condition to allow specific IPs */
   res.status(405).send('<!doctype html>
     <head>
       <title>PURGE Not allowed</title>
     </head>
     <body>
       PURGE Not allowed
     </body>
   </html>');
  }
});

I know Varnish is more suitable if you want a simple dynamic solution.

Hope this will help as I currently don't have the infrastructure to test this.