For more information regarding the security incident at F5, the actions we are taking to address it, and our ongoing efforts to protect our customers, click here.

Weblogic Persistence done right ;=)

Problem this snippet solves:

You want to use your Weblogic issued JSESSIONID session cookie to control persistence.
A sensible option would be to employ a Cookie Hash persistence profile but then you find it to be deficient in these respects:

  • Mishandling of stale session cookies: A client making a request with a stale session cookie will cause the LTM to insert that stale session identifier into the persistence table.
  • No support for cookie-less User-Agents whereby the session id is encoded in the URL.
  • No tcl commands to query the cookie persistence table (e.g. for debug purposes).

As opposed to other Weblogic Persistence iRules found in Codeshare this irule will also allow for:

  • Minimizing the number of persistence records by persisting on the JVMID alone. That means there will be as many records as there are Weblogic Application Server instances.
  • Treating JSESSIONID value as opaque (i.e. no tolower thank you very much :)).
  • Greater control of debug logging.

How to use this snippet:

If your Virtual Server services more than one application and/or pool, don't forget to employ a one-connect profile or attach an iRule that does

LB::detach
in then response event (see SOL7964).
It is assumed pool-selection is done in a LTM Policy otherwise, if done by iRule, take care of the order of iRule execution.

Code :

# Weblogic Persist iRule, Version 0.93
# Mars, 2012
# Last update: Aug, 2012
# Updated v11.6.0: 15/02/2015

# Created by Opher Shachar (contact me through devcentral.f5.com)

# Purpose:
# This iRule persists requests based on the JSESSIONID cookie issued by the
# Weblogic server. Since Weblogic appends its JVMID to the cookie, it affords
# us the chance to persist on just the JVMID minimizig the size of the 
# persistence table.
# If not in a cookie the JSESSIONID will be searched for in the request uri.

when RULE_INIT {
   # Set debug level to: 0, 1 or 2
   set static::Weblogic_debug 1
   # Persist on JVMID only (e.g., to minimize the persist-record table)
   set static::Weblogic_JVMID 0
   # Set the name and length of the Weblogic session cookie
   set static::Weblogic_CookieName "JSESSIONID"
   set static::Weblogic_PathName   "jsessionid="
   set static::Weblogic_PathLen    [string length $static::Weblogic_PathName]
   # Set a timeout of 12 hours (43,200 seconds)
   set static::Weblogic_timeout    43200
}

when CLIENT_ACCEPTED {
   set log_prefix "Client [IP::client_addr]:[TCP::client_port]"
}

when HTTP_REQUEST {
   # Log details for the request
   if {$static::Weblogic_debug > 1} {
      log local0. "$log_prefix: Request to [HTTP::uri] with cookie: [HTTP::cookie value $static::Weblogic_CookieName]"
   }

   # Check if there is a session cookie
   set pkey [HTTP::cookie $static::Weblogic_CookieName]
   if {$pkey eq ""} {
      # Perhaps there's a jsessionid in the request uri. The jsessionid, 
      # when included is in the path: /path/to/file.ext;jsessionid=abcd!1234
      set pkey [findstr [HTTP::path] $static::Weblogic_PathName $static::Weblogic_PathLen]
   }

   # Did we find a session id?
   if {$pkey ne ""} {
      # Extract the JVMID, if none then pkey is unchanged
      set jvmid [findstr $pkey ! 1]
      if {$static::Weblogic_JVMID and ($jvmid ne "")} { set pkey $jvmid }

      # Persist off of the session id value with the set timeout
      if {[persist lookup uie $pkey] ne ""} {
         persist uie $pkey $static::Weblogic_timeout
         if {$static::Weblogic_debug > 1} {
            log local0. "$log_prefix: Used persistence record from cookie or path: [persist lookup uie $pkey]"
         }
      } else {
         # Client gave stale session id  --  don't persist
         persist none
         if {$static::Weblogic_debug > 0} {
            log local0. "$log_prefix: No persistence record found for key: $pkey"
         }
      }
   } else {
      # Client gave no session id  --  don't persist
      persist none
      if {$static::Weblogic_debug > 1} {
         log local0. "$log_prefix: No session id given in cookie or path."
      }
   }
}

when HTTP_RESPONSE {
   # Check if there is a session cookie in the response
   set pkey [HTTP::cookie $static::Weblogic_CookieName]
   if {$pkey eq "" and [HTTP::is_redirect]} {
      # Perhaps there's a jsessionid in the redirect uri. The jsessionid, 
      # when included is in the path: /path/to/file.ext;jsessionid=abcd!1234
      set pkey [findstr [URI::basename "[HTTP::header Location]"] $static::Weblogic_PathName $static::Weblogic_PathLen]
   }

   # Did we find a session id?
   if {$pkey ne ""} {
      # Extract the JVMID, if none then pkey is unchanged
      set jvmid [findstr $pkey ! 1]
      if {$static::Weblogic_JVMID and ($jvmid ne "")} { set pkey $jvmid }

      # Persist the session id value with the set timeout
      persist add uie $pkey $static::Weblogic_timeout
      if {$static::Weblogic_debug > 0} {
         set val [persist lookup uie $pkey]
         log local0. "$log_prefix: Added persistence record from cookie or redirect: $pkey -> $val"
      }
   }
}

Tested this on version:

11.4
Updated Jun 06, 2023
Version 2.0
No CommentsBe the first to comment