Varnish VCL to get a header from the origin and associate it with a sessionid for future cache lookups

286 Views Asked by At

We have a number of user roles, and would like Varnish to cache the authenticated pages as many users are in each role.

In theory, we could add the role code to the request, eg, as a cookie, then strip sessionid and use that role code value in the key when storing the page in cache. But this opens a security hole, if someone copies the role code into their cookie.

Could the origin server add a header to the response with the role key, and Varnish extract it (on first delivery to that session), and associate it with a sessionid, in private, shared Varnish server memory space, and then when a future request from this session comes in, look up the role code based on sessionid, and use that to construct the cache key?

This seems secure, as Varnish only trusts the role from the origin, but is it possible?

Or is there a better way?

1

There are 1 best solutions below

2
PajE On

hum... you might try to transform your varnish into an api gateway.. via the vmod_curl (opensource). it would be easier/safer with the varnish software/entreprise modules (vmod_http and vmod_headerplus)

So the end-user is getting an authorization bearer, which might be safe.. and the varnish cache is hashed with roles (who are expected to be fewer that the users)

very roughly:

import curl;

vcl_recv {
   if (req.http.authorization) {

      set req.http.bearer-authorization = regsub(req.http.authorization,"^Bearer (.*)$","\1");
      if (req.http.bearer-authorization) {

           curl.header_add("Authorization:" + req.http.bearer-authorization);
           curl("https://myoauthwebsite/oauth");
           if (curl.status() == 200) {
              set http.req.x-roles = curl.body();
           }
           curl.free()
           unset req.http.bearer-authorization;
      }

      unset req.http.authorization; # without the unset, no-cache

      ...
}
vcl_hash {
   if (http.req.x-roles) {
      hash_data(http.req.x-roles);
   }
}

To achieve high rates, you might also put your oauth server behind your varnish configuration (so your curl would be something like curl("127.0.0.1");

As Nils explained, you might also store everything in a JWT token.