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.

Open SSO Authentication

Problem this snippet solves:

A simple "Policy Agent" iRule that ensures that all incoming HTTP requests are authenticated against the OpenSSO server(s). I am by no means an iRule programmer, so I'm sure this can be optimized. So far it has been working for me, but if you find any bugs please let me know!

Code :

# OpenSSO "Policy Agent" that merely checks that the incoming request is from an authenticated
# user.  If not, the user is redirected to the appropriate Login UI until a valid SSO token
# is received
#
# this iRule is just a modified version of the code present by "deb" at
# http://devcentral.f5.com/s/Default.aspx?tabid=63&articleType=ArticleView&articleId=105

when RULE_INIT {
# set up the global variables we will need throughout the course of this iRule
# most of the customization to handle your specific deployment should be made here

set ::ckname "iPlanetDirectoryPro"

set domain ".example.com"
set expired_token "$::ckname=\"LOGOUT\"; expires=Fri, 31-Dec-2000 23
set expired_amlb "amlbcookie=\"LOGOUT\"; expires=Fri, 31-Dec-2000 23
set ::expired_cookies " Set-Cookie $expired_token Set-Cookie $expired_amlb"

# done with the intermediate strings now
unset domain
unset expired_token
unset expired_amlb

set ::loginUI "https://distauth.example.com:3443/da/UI/Login?goto=%s"

set ::valid_string "boolean=true"
}

when CLIENT_ACCEPTED {
# when the user has been authenticated, this will be set to the valid token
set validCookie ""
}

when HTTP_REQUEST {
# these are the incoming HTTP requests which we have not checked yet. check against
# the OpenSSO server to ensure this is an authenticated user

if {[HTTP::cookie exists $::ckname]} {
set tokenid [string trimleft [HTTP::cookie value $::ckname] "\""]
set tokenid [string trimright "$tokenid" "\""]

if {[string length $validCookie] > 0 && $validCookie eq $tokenid} {
pool pool_policyagent
} else {
set validCookie ""

# if client hasn't already been validated, save the
# request so we can replay it to the LB server later
set LB_request [HTTP::request]

# inject lookup URI in place of original request
HTTP::uri "/opensso/identity/isTokenValid?tokenid=[URI::encode $tokenid]"

# and send the out-of-band validation query to the OpenSSO pool.
pool pool_opensso
}
} else {
# this request doesnt even have a token to validate, so we need to redirect the the Login UI
HTTP::redirect [format "$::loginUI" [URI::encode "https://[HTTP::host][HTTP::uri]"]]
}
}

when HTTP_RESPONSE {
# If validCookie is empty in response event, this is the response
# to the opensso check, so we collect entire payload (up to 16byte limit)
# to evaluate the OpenSSO response and to prevent this response
# from being returned to the client.
# Already-validated connections will bypass the rest of the rule.

if {[string length $validCookie] <= 0} {
if {[HTTP::header exists Content-Length] && ([HTTP::header Content-Length] < 16)} {
set clength [HTTP::header Content-Length]
} else {
set clength 16
}

HTTP::collect $clength
}
}

when HTTP_RESPONSE_DATA {
# HTTP_RESPONSE_DATA will only be triggered for an OpenSSO check.
# (All other requests have already been forwarded to the Policy Agent pool.)
# If response from OpenSSO indicates authentication, save the token
# and replay the original request to the Policy Agent pool. Otherwise, clear
# the users cookies and redirect to the Login UI

if {[HTTP::payload] contains $::valid_string} {
pool pool_policyagent
HTTP::retry $LB_request

# assume all further requests with this token are valid
regexp {iPlanetDirectoryPro=\"([^\s]*)\"[;]?} $LB_request totalMatch validCookie
unset totalMatch
} else {
# if we had a cookie, we dont now
set validCookie ""

# remove the invalid cookies and redirect to LoginUI
regexp {Host: ([^\s\t]*)\s} $LB_request totalMatch host
regexp {[GET|POST] (/.*) HTTP} $LB_request totalMatch uri
unset totalMatch

HTTP::respond 302 Location [format "$::loginUI" [URI::encode "https://$host$uri"]] $::expired_cookies
}
}

when LB_FAILED {
log local0.debug "PolicyAgent: LB failed for: [LB::server]"
log local0.debug "PolicyAgent: LB status: [LB::status]"
}
Published Mar 18, 2015
Version 1.0
No CommentsBe the first to comment