Set the SameSite Attribute for LTM Persistence Cookies

Problem this snippet solves:

Chrome (and likely other browsers to follow) will enforce the SameSite attribute on HTTP cookies to Lax beginning soon (initial limited rollout week of Feb 17th, 2020) which could impact sites that don't explicitly set the attribute. This iRule will add the SameSite attribute to LTM persistence cookies.


Contributed by: hoolio

How to use this snippet:

Apply the iRule to the appropriate virtual servers.

Code :

when HTTP_RESPONSE_RELEASE {

    # Log debug to /var/log/tlm? 1=yes, 0=no
    set persist_cookie_dbg 1

    # Set the SameSite cookie attribute value to one of: Strict, Lax or None
    #
	# None: Cookies will be sent in both first-party context and cross-origin requests; 
	#	however, the value must be explicitly set to None and all browser requests must 
	#	follow the HTTPS protocol and include the Secure attribute which requires an encrypted 
	#	connection. Cookies that don't adhere to that requirement will be rejected.
	#	Both attributes are required together. If just None is specified without Secure or 
	#	if the HTTPS protocol is not used, the third-party cookie will be rejected.
	#
	# Lax: Cookies will be sent automatically only in a first-party context and with HTTP GET requests. 
	#	SameSite cookies will be withheld on cross-site sub-requests, such as calls to load images or iframes, 
	#	but will be sent when a user navigates to the URL from an external site, e.g., by following a link.
	#
	# Strict: browser never sends cookies in requests to third party domains
	#
	#	Above definitions from: https://docs.microsoft.com/en-us/microsoftteams/platform/resources/samesite-cookie-update 
	set samesite_security "none"


    # Exit this rule if the VS does not have a persist cookie profile attached
    if {not [PROFILE::exists persist cookie]}{
        if {$persist_cookie_dbg}{log local0. "[IP::client_addr]:[TCP::client_port]: Exiting because there isn't a cookie persist profile on the VS"}
        return
    }

    # Get the persistence cookie profile cookie name
    # [PROFILE::persist mode cookie cookie_name] returns:
    #   - a runtime error, if a persist profile isn't defined on the VS
    #   - a null length string, if the cookie persist profile doesn't have a cookie name set (which is the default)
    #   - the cookie name, if the cookie persist profile has a custom cookie name set
    if {[set persist_cookie [PROFILE::persist mode cookie cookie_name]] ne ""}{
        # Above command returned a custom cookie name from the persistence profile
        if {$persist_cookie_dbg}{log local0. "[IP::client_addr]:[TCP::client_port]: \$persist_cookie=$persist_cookie"}
    } else {
        # Cookie persist profile does not have a custom cookie name set, so derive it from the pool name, using the format BIGipServer
        set persist_cookie "BIGipServer[LB::server pool]"
    }
    if {$persist_cookie_dbg}{log local0. "[IP::client_addr]:[TCP::client_port]: Parsed persist cookie name=$persist_cookie"}

    # Set the samesite cookie attribute on the persistence cookie
    switch [string tolower $samesite_security] {
        "none" {
            # samesite=none requires the Secure flag also be set
        	HTTP::cookie attribute $persist_cookie insert "SameSite" "None"
        	HTTP::cookie secure $persist_cookie
        }
        "lax" -
        "strict" {
        	HTTP::cookie attribute $persist_cookie insert "SameSite" $samesite_security
        }
        default {
            if {$persist_cookie_dbg}{log local0. "[IP::client_addr]:[TCP::client_port]: Invalid SameSite attribute value ''. \
                Needs to be one of None|Lax|Strict"}
        }
	}
	# Log the Set-Cookie header values
	if {$persist_cookie_dbg}{log local0. "[IP::client_addr]:[TCP::client_port]: Set-Cookie header values=[HTTP::header values {set-cookie}]"}
}

# Log examples:

# No cookie persist profile enabled on the virtual server:
: 10.1.1.8:51193: Exiting because there isn't a cookie persist profile on the VS

# Default cookie persist profile enabled on the virtual server (no persist cookie name is explicitly defined)
: 10.1.1.8:51215: Parsed persist cookie name=BIGipServer/Common/http_pool
: 10.1.1.8:51215: Set-Cookie header values={BIGipServerhttp_pool=117506314.20480.0000; path=/; Httponly; Secure}

# Custom cookie persist profile enabled on the virtual server with a custom cookie name defined as "my_persist_cookie"
: 10.1.1.8:51255: $persist_cookie=my_persist_cookie
: 10.1.1.8:51255: Parsed persist cookie name=my_persist_cookie
: 10.1.1.8:51255: Set-Cookie header values={my_persist_cookie=117506314.20480.0000; path=/; Httponly; Secure;SameSite=None}

Tested this on version:

13.0
Published Feb 06, 2020
Version 1.0

Was this article helpful?

3 Comments

  • Hoolio's avatar
    Hoolio
    Ret. Employee

    This more current iRule handles setting SameSite on LTM persistence cookies and includes special handling for user-agents that don't support SameSite=None on cookies:

     

    https://devcentral.f5.com/s/articles/iRule-to-set-SameSite-for-compatible-clients-and-remove-it-for-incompatible-clients-LTM-ASM-APM

  • Greetings,

     

    Is there a 11.5.X version.   

    11.5.X returns an error with HTTP::cookie attribute syntax.

    Thank you in advance

  • Hoolio's avatar
    Hoolio
    Ret. Employee

    Hi Orlando,

     

    There is a link in this article to a v11 compatible version on github:

     

    https://github.com/f5devcentral/irules-toolbox/blob/master/security/http/cookies/samesite-attributes-pre-v12.tcl

     

    The latter iRule will work for v11, but uses more CPU cycles because we don't have the HTTP::cookie attribute sub-command until v12.0. If at all possible, I'd suggest upgrading your v11.5 BIG-IPs to a supported software version. v11.5 has reached End of Software Development in 2019 and therefore doesn't get security fixes. End of Technical Support for v11.5 is coming in April:

     

    K5903: BIG-IP software support policy

    https://support.f5.com/csp/article/K5903

     

    Aaron