Score:0

Update request cookie for Varnish ESI-include requests from initial `beresp`

cn flag

I have an application that is fronted by a Varnish server. Parts of the page is rendered using ESI includes.

My problem is that the upstream response includes an encrypted session cookie, which among other things contains a CSRF token (no server-side session storage at all).

For an initial request (no cookie in the request), the ESI requests will not include a cookie set by the first response from the upstream server.

I've tried setting req.http.Cookie in the vcl_deliver hook, as it's the only place in the request flow I've found where both req and res are R/W accessible. However, looking at the requests with varnishlog reveals the ESI requests are unaffected and don't include the cookie.

I've done my best to trawl through the documentation, but can't find anything remotely useful.

Is it possible to achieve what I want, i.e. update req so that the ESI requests include the cookie returned by the initial upstream response?

Score:1
in flag

We need to make a clear distinction between a request containing a Cookie header and a response containing a Set-Cookie header.

Assuming a CSRF token was set through a Set-Cookie header of the parent response, you probably want to access that value through a Cookie request header in your ESI subrequest.

Assuming the Cookie header already contains the CSRF token

The req_top.http.Cookie variable has access to the cookies of the parent request, however req_top not accessible in vcl_backend_response where the ESI placeholders are parsed.

You can bypass this limitation with the following VCL snippet:

sub vcl_recv {
    if (req.esi_level > 0 ) {
        set req.http.X-Parent-Cookie = req_top.http.Cookie;
    }
}

This will enable the X-Parent-Cookie header which is available in vcl_backend_response through bereq.http.X-Parent-Cookie.

Assuming the Cookie header does not yet contain the CSRF token

It is realistic to assume that req_top.http.Cookie doesn't yet contain the value of the CSRF token because when ESI subrequests are processed, the Cookie header is not yet set by the client.

The only solution I can think off is storing the parent Set-Cookie value in a variable. Variables aren't supported natively in Varnish and require the official https://github.com/varnish/varnish-modules to be installed.

You'll have to compile this from source.

See https://github.com/varnish/varnish-modules/blob/master/src/vmod_var.vcc for the vmod_var API and code examples.

cn flag
THANK YOU! I completely forgot about `req_top`.
cn flag
To elaborate a bit, I amend `req` in `vcl_deliver`, setting `req.http.X-Updated-Cookie` when `req.do_esi == true`. Then in `vcl_recv`, when `req.esi_level > 0`, if `req_top.http.X-Update-Cookie` is set I copy it into `req.http.Cookie`. Works a treat. Thankfully global vars not required.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.