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