Skip to content

Fix Session Affinity With Partitioned Session Cookies #529

@hoffmaen

Description

@hoffmaen

Current behavior

There are currently two issues/bugs/unexpected behaviors with Partitioned Session Cookies in Gorouter.

The issues described here originate from the fact that CHIPS (Cookies Having Independent Partitioned State) introduces a new dimension to cookies (see RFC6265bis), allowing multiple cookies with the same name, domain, and path but different partitioned attributes to co-exist. The cookie attributes reside on the client side and are not sent to the server.

0. Session Affinity a/k/a Sticky Sessions - Green Path

The following diagram shows how session affinity in Gorouter works in generel:
Image

1. Defaulting to Issue Non-Partitioned Cookie

Gorouter sets an unpartitioned VCAP_ID cookie when the provided one points to a non-existent instance and no new JSESSIONID cookie was issued by the application.

Context

This issue arises when an application instance sets a partitioned JSESSIONID cookie in the response (causing Gorouter to add a partitioned VCAP_ID cookie), and subsequently, this application instance becomes unavailable.

The next request (containing partitioned VCAP_ID and partitioned JSESSIONID cookies) reaches Gorouter, but Gorouter cannot route to the instance referenced by the VCAP_ID cookie. In this case, Gorouter's default behavior is to route the request to another available instance. When that instance responds without a JSESSIONID cookie, Gorouter will always set a new unpartitioned VCAP_ID cookie.

Problem

This leaves the client with:

  • A partitioned JSESSIONID cookie
  • A partitioned VCAP_ID cookie referencing a non-existent app instance
  • An unpartitioned VCAP_ID cookie referencing an existing instance

This creates problems in two scenarios:

  • Non-Third-Party Context: The client sends all three cookies to Gorouter. Gorouter will either pick the partitioned VCAP_ID cookie first (routing the request to an arbitrary instance) or pick the unpartitioned cookie first (routing it to the instance referenced in that cookie).
  • Third-Party Context: Cookie sandboxing is broken because the new VCAP_ID does not have the partitioned attribute, causing it to be sent to any host embedding the application. Additionally, the client sends both the (orphaned) partitioned and unpartitioned VCAP_ID cookies, and Gorouter will prefer one depending on client behavior.
Image

Solution

Gorouter defaults to creating a non-partitioned VCAP_ID cookie in this case because cookie attributes are not part of the cookie header sent by the client. Gorouter does not know whether the client-side VCAP_ID cookie referencing an invalid instance has the partitioned flag set, and therefore cannot create a new cookie with the same attributes as the old one.

Proposal: Gorouter should not create new VCAP_ID cookies when the referenced instance is invalid and the application does not set a new JSESSIONID cookie. This might break existing scenarios.

2. Gorouter Only Translates the First JSESSIONID Cookie to a VCAP_ID Cookie

Context

Google describes a migration strategy for CHIPS that addresses the issue of partitioned and non-partitioned cookies co-existing. They propose the following migration approach: When migration begins, the application sets two cookies:

  • A partitioned cookie
  • An unpartitioned cookie with Max-Age=0, which immediately invalidates the cookie

Problem

Applications on Cloud Foundry cannot implement this strategy because it interferes with the VCAP_ID cookie set by Gorouter.

Gorouter currently only parses the first JSESSIONID cookie and creates a VCAP_ID cookie based on it. Then, Gorouter breaks out of the loop.

For correct implementation, when an application sets both JSESSIONID cookies as described above, Gorouter needs to "translate" both cookies to VCAP_ID cookies and copy the attributes (Partitioned state, Max-Age) from the JSESSIONID cookies to each VCAP_ID cookie.

Image

Solution

Gorouter must support the proposed migration strategy.

Proposal: Gorouter should not break out of the loop when iterating through response cookies. Instead, it should create one VCAP_ID cookie per JSESSIONID cookie and copy all attributes, even when there are multiple JSESSIONID cookies.

Affected Version

current

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    Inbox

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions