Ya' row ze: Lets go!

You are here

Configure varnish to cache httpauth protected files

Some environments need to be behind some form of authentication to keep prying eyes out, but, they might still want to take advantage of varnish's caching ability. The specific way I'm attempting to protect the environment is to use basic-auth from apache. The main issue though is that Varnish by default (and within nearly every VCL example I've found) specifically bypasses the cache when the Authorization header is in place. How then can both be achieved?

Discussions with teams using a similar technology (in this case Akamai) mentioned that they configure their backend to generate a cookie in combination with the authorization header, as well as keep a shared salt between the backend and Akamai. The cookie - assigned after successful authorization - is simply a hash of the Client IP, the Authorization header value, and the shared salt value. It is then up to Akamai to test for the existence of both the cookie, and the Authorization header. If neither (or only one) exists, authorization is required, and akamai can "pass" the request on. Once both items exist, akamai has to do a quick hash of the 3 values it can deduce, and if that matches the cookie, It'll serve from it's cache.

The question now is really, can varnish do the same thing in a VCL?

Looking at the default VCL's provided by varnish, the following lines look like a good place to start:

if (req.http.Authorization) {
return(pass);
}

This certainly the code to target. It looks like the modification should be pretty simple:

# To achieve http_auth with caching, a special cookie needs to be generated
# that corresponds to the authorization ticket. If this is desired, it needs
# to be generated by the backend. If that cookie doesn't exist
if ((req.http.cookie ~ "(^|;\s*)YOUR_COOKIE_NAME_HERE=") && (req.http.Authorization)){
#check the hashed value of the combined headers - authorization, ip, salt

#note: saltymcsalterson is just a random salt I thought up, and needs to be changed.
if(regsub(req.http.cookie, "aktuaucov2=([a-zA-Z0-9]+)", "\1") !== digest.hash_md5(req.http.Authorization + client.ip + "saltymcsalterson") ){
return(pass);
}
}
# There is no authorization header or confirmation cookie. Pass on caching
else {
return(pass);
}

Back to top