Forum Discussion
Moe_Jartin
Cirrus
May 26, 2010LDAP Authentication iRule... HELP
I am trying to write an iRule for an LDAP authentication profile. The irule will take the value of a cookie from every request and use it as the username AND password for which it will then validate against LDAP. I also want it to check to see if an existing session exist and allow the traffic based on the local session rather than querying LDAP for EVERY HTTP request.
I took the Code Share iRule from http://devcentral.f5.com/wiki/default.aspx/iRules/ClientAuthUsingHTMLForms.html and altered it a bit to fit my scenario. I have it working to the point that it is querying LDAP and if the cookie does not exist in the irule or if the cookie value is not valid then acces is denied. The part that is not working is the creation and checking of the local session table. It is querying LDAP for EVERY HTTP request.
There are certainly pieces to this irule that I do not understand so I am looking for help to understand how to create a session in the table and check that to see if a session exist for that user before querying LDAP.
when CLIENT_ACCEPTED {
set forceauth 1
set auth_status 2
set ckname LDSDEVKEY
set ckpass myPassword
set asid [AUTH::start pam default_ldap]
}
when HTTP_REQUEST {
if { [matchclass [HTTP::path] starts_with "/opensso"] } {
Private URI, Auth Required
if { [HTTP::header exists $ckname] } {
set ldsdevkey [HTTP::header value $ckname]
if { not ( $ldsdevkey equals "" ) } {
log local0. "LDSDEVKEY=$ldsdevkey"
retrieve the auth status from the session table
set auth_status [session lookup uie $ldsdevkey]
}
If the auth status is 0 then the user is authenticated
if { $auth_status eq 0 } {
LDSDEVKEY & Session Auth valid
set forceauth 0
}
if {$forceauth eq 1} {
set auth_username $ldsdevkey
set auth_password $ldsdevkey
AUTH::username_credential $asid $auth_username
AUTH::password_credential $asid $auth_password
AUTH::authenticate $asid
HTTP::collect
}
}
}
}
when AUTH_SUCCESS {
if {$asid eq [AUTH::last_event_session_id]} {
Now the user has authenticated lets give them an encrypted cookie with their authID
We'll also add the AUTH::status to a session entry with the authID as the key
We can then re-direct the user to the page they originally asked for
set authStatus [AUTH::status $asid]
session add uie $asid $authStatus 1800
}
}
when AUTH_FAILURE {
if {$asid eq [AUTH::last_event_session_id]} {
HTTP::respond 200 content "Authentication Failed"
}
}
when AUTH_WANTCREDENTIAL {
if {$asid eq [AUTH::last_event_session_id]} {
HTTP::respond 200 content "Authentication Credentials not provided"
}
}
when AUTH_ERROR {
if {$asid eq [AUTH::last_event_session_id]} {
HTTP::respond 200 content "Authentication Error"
}
}
- hoolio
Cirrostratus
I think you'd want to use HTTP::cookie to get the value for a cookie--not HTTP::header. I don't see where you're setting the cookie either. Is the application doing this? - Moe_Jartin
Cirrus
Aaron, - Moe_Jartin
Cirrus
OK, apparently I was very confused. Originally, I had tried the iRule mentioned above but never got it to work. Sorry, I was working on this a while ago and then just came back to it and forgot what I had done.when HTTP_REQUEST { set ldsdevkey [HTTP::header value LDSDEVKEY] if {not [info exists tmm_auth_http_sids(ldap)]} { set tmm_auth_sid [AUTH::start pam default_ldap] set tmm_auth_http_sids(ldap) $tmm_auth_sid if {[info exists tmm_auth_subscription]} { AUTH::subscribe $tmm_auth_sid } } else { set tmm_auth_sid $tmm_auth_http_sids(ldap) } AUTH::username_credential $tmm_auth_sid $ldsdevkey AUTH::password_credential $tmm_auth_sid $ldsdevkey AUTH::authenticate $tmm_auth_sid if {not [info exists tmm_auth_http_collect_count]} { HTTP::collect set tmm_auth_http_successes 0 set tmm_auth_http_collect_count 1 } else { incr tmm_auth_http_collect_count } } when AUTH_RESULT { if {not [info exists tmm_auth_http_sids(ldap)] or \ ($tmm_auth_http_sids(ldap) != [AUTH::last_event_session_id]) or \ (not [info exists tmm_auth_http_collect_count])} { return } if {[AUTH::status] == 0} { incr tmm_auth_http_successes } If multiple auth sessions are pending and one failure results in termination and this is a failure or enough successes have now occurred if {([array size tmm_auth_http_sids] > 1) and \ ((not [info exists tmm_auth_http_sufficient_successes] or \ ($tmm_auth_http_successes >= $tmm_auth_http_sufficient_successes)))} { Abort the other auth sessions foreach {type sid} [array get tmm_auth_http_sids] { unset tmm_auth_http_sids($type) if {($type ne "ldap") and ($sid != -1)} { AUTH::abort $sid incr tmm_auth_http_collect_count -1 } } } If this is the last outstanding auth then either release or respond to this session incr tmm_auth_http_collect_count -1 if {$tmm_auth_http_collect_count == 0} { unset tmm_auth_http_collect_count if {[AUTH::status] == 0} { HTTP::release } else { HTTP::respond 401 } } }
- hoolio
Cirrostratus
Hi Joe,when HTTP_REQUEST { Get the key value from the header set ldsdevkey [HTTP::header value LDSDEVKEY] Do something if there is no value for the key? if {$ldsdevkey eq ""}{ HTTP::respond 401 return } Check if there is an existing session for the key if {[session lookup uie $ldsdevkey] ne ""}{ There is an existing session for this key, so don't do any auth for this request return } if {not [info exists tmm_auth_http_sids(ldap)]} { set tmm_auth_sid [AUTH::start pam default_ldap] set tmm_auth_http_sids(ldap) $tmm_auth_sid if {[info exists tmm_auth_subscription]} { AUTH::subscribe $tmm_auth_sid } } else { set tmm_auth_sid $tmm_auth_http_sids(ldap) } AUTH::username_credential $tmm_auth_sid $ldsdevkey AUTH::password_credential $tmm_auth_sid $ldsdevkey AUTH::authenticate $tmm_auth_sid if {not [info exists tmm_auth_http_collect_count]} { HTTP::collect set tmm_auth_http_successes 0 set tmm_auth_http_collect_count 1 } else { incr tmm_auth_http_collect_count } } when AUTH_RESULT { if {not [info exists tmm_auth_http_sids(ldap)] or \ ($tmm_auth_http_sids(ldap) != [AUTH::last_event_session_id]) or \ (not [info exists tmm_auth_http_collect_count])} { return } if {[AUTH::status] == 0} { Auth was successful, so add the key to the session table The value doesn't matter, so use anything session add uie $ldsdevkey 1 1800 incr tmm_auth_http_successes } If multiple auth sessions are pending and one failure results in termination and this is a failure or enough successes have now occurred if {([array size tmm_auth_http_sids] > 1) and \ ((not [info exists tmm_auth_http_sufficient_successes] or \ ($tmm_auth_http_successes >= $tmm_auth_http_sufficient_successes)))} { Abort the other auth sessions foreach {type sid} [array get tmm_auth_http_sids] { unset tmm_auth_http_sids($type) if {($type ne "ldap") and ($sid != -1)} { AUTH::abort $sid incr tmm_auth_http_collect_count -1 } } } If this is the last outstanding auth then either release or respond to this session incr tmm_auth_http_collect_count -1 if {$tmm_auth_http_collect_count == 0} { unset tmm_auth_http_collect_count if {[AUTH::status] == 0} { Auth was successful, so add the key to the session table The value doesn't matter, so use anything session add uie $ldsdevkey 1 1800 HTTP::release } else { HTTP::respond 401 } } }
- Moe_Jartin
Cirrus
Aaron, - Mants_57436
Nimbostratus
Hi guys, - Kevin_Stewart
Employee
You're talking about something I'd call "post-access authentication". Take a look at this section of the Wiki for SSL client certificate authentication.when HTTP_REQUEST { if { not ( [HTTP::uri] starts_with "/test" ) } { ACCESS::disable } }
Recent Discussions
Related Content
DevCentral Quicklinks
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
Discover DevCentral Connects