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.

Insert header for APM policy

Problem this snippet solves:

This iRule requires the APM module to work

The goal is to pass the username for an authenticated session used during APM login as a HTTP header to the backend server.

Overall logic is based on ClientAuthUsingHTMLForms and the AUTH event was replaced by the ACCESS_POLICY_COMPLETED event.

  1. ACCESS_POLICY_COMPLETED sets a custom cookie containing session.logon.last.username and session.user.sessionid after successful login
  2. HTTP_REQUEST parses custom cookie and compares it with the MRHSession cookie. If they match the username will be added as an HTTP header.

Code :

when RULE_INIT {
# Set key for encryption. 
# Use a hardcoded key to avoid a global variable, one key per TMM or generating a new key on every reload of RULE_INIT
#set static::auth_cookie_aes_key [AES::key 128]
set static::auth_cookie_aes_key "AES 128 abcdef1234567890abcdef1234567890"
}
when CLIENT_ACCEPTED {
# set the Name of the Base64 Encoded Cookie send to the client
set ckname BIGIP_AUTH
# set the Name of the BigIP APM module session cookie (default MRHSession)
set apmmrhsession MRHSession
# set the Name of HTTP Header send to the Backend system
set httpmyheader BIGIP_USER
# set a Password which will be added to the APM SessionID & Username to make it more complex
set ckpass YourVerySecret
}

when HTTP_REQUEST {
# remove Header httpmyheader from request if injected by Client
HTTP::header remove $httpmyheader

# Check if my ckname and MRHSession cookie exist
if { [HTTP::cookie exists $apmmrhsession ] && [HTTP::cookie exists $ckname ] }
{
# get the value of the MRHSession cookie and check if it is a existing APM session
set apmcookie [HTTP::cookie value $apmmrhsession]
if { [ACCESS::session exists $apmcookie] }
{
log local0. "MRHSession Cookie value: $apmcookie with ID on last 8 [substr $apmcookie 24]"
# Get Cookie values and decrypt
set httpmycookie [HTTP::cookie value $ckname]
set httpmydecrytedcookie [AES::decrypt $static::auth_cookie_aes_key [b64decode $httpmycookie ]]

# Check if Cookie is not Empty
if { not ( $httpmydecrytedcookie equals "" ) }
{
# get the Username and sessionID out of the cookie
# it was set with: set composedapmid [format "%s&%s&%s" $apmsessionid $apmsessionuser $ckpass]
set httpmycookievals [split $httpmydecrytedcookie "&"]
set httpmycookieuser [lindex $httpmycookievals 1]
set httpmycookieid [lindex $httpmycookievals 0]
#log local0. "retrieved username $httpmycookieuser with sessionID $httpmycookieid from $ckname cookie"

# check if sessionID from ckname cookie match the last 8 chars of the MHRSession ID
if { $httpmycookieid equals [substr $apmcookie 24] }
{
log local0. "APM Policy Allowed Access for user $httpmycookieuser with sessionID $httpmycookieid"
# Insert Header for Backendsystem
HTTP::header insert $httpmyheader $httpmycookieuser
} else {
# do what ever is needed if the cookie values don't match
# cookies were modified by the client
# e.g. deny access
HTTP::respond 403 content {


Access Denied - session unknown


Access Denied - session unknown
You are not allowed to access this system.


} noserver
}
}
} else {
# all Cookies found but no entry in ACCESS::session
#log local0. "No MRHSession found"
}
} else {
# either MRHSession cookie or spmmycookie is missing
# a) new request without MRHSession
# b) ACCESS_POLICY_COMPLETED not run (client retrieves objects for APM login page
# do nothing
}

}

when ACCESS_POLICY_COMPLETED {
set policy_result [ACCESS::policy result]
switch $policy_result {
"allow" {
#new session which passed APM Policy
#generate my own cookie for HTTP_REQUEST requests
#get major session information
set apmsessionid [ACCESS::session data get "session.user.sessionid"]
set apmsessionuser [ACCESS::session data get "session.logon.last.username"]
set apmsessionlanding [ACCESS::session data get "session.server.landinguri"]

# compose Username and Session together with a secret
set composedapmid [format "%s&%s&%s" $apmsessionid $apmsessionuser $ckpass]
# b64 Encode the AuthID so it can be stored in the Cookie at the Client
set encrypted_apmid [b64encode [AES::encrypt $static::auth_cookie_aes_key $composedapmid]]
# build the Cookie string from: $ckname=CookieName, $encrypted_apmid=b64encoded apmid
set apmmycookie [format "%s=%s ; path=/; " $ckname $encrypted_apmid ]

#respond with a 302 redirect to original URI with cookie
ACCESS::respond 302 Location $apmsessionlanding "Set-Cookie" $apmmycookie
log local0. "APM Policy Allowed Access for user $apmsessionuser with ID $apmsessionid"
}
"deny" {
ACCESS::respond 401 content "Error: Failure in Authentication" Connection Close
log local0. "APM Policy Denied Access"
}
}
}
Published Mar 18, 2015
Version 1.0
No CommentsBe the first to comment