APM Clientless certificate authentication
Problem this snippet solves:
This code allow to configure certificate authentication with APM clientless-mode support.
The APM behavior when configuring following condition is to disable clientless-mode :
- APM clientless-mode in irule
- On-Demand Cert Auth in VPE
This code enable clientless mode if required based.
PS : this code use a list instead of a simple variable to be included in APM Sharepoint authentication code without changes.
How to use this snippet:
Edit the first HTTP_REQUEST event and add condition for enabling certificate authentication.
Code :
when HTTP_REQUEST { set AUTHENTICATION_MODE {certificate} #set AUTHENTICATION_MODE {none} } priority 900 when CLIENTSSL_CLIENTCERT { if {[SSL::cert count] < 1}{ reject } else { HTTP::release } } when HTTP_REQUEST { if { ( [set apm_sessionid [HTTP::cookie value "MRHSession"]] ne "" ) and ( [ACCESS::session exists -state_allow $apm_sessionid] ) } then { # Allow the successfully pre authenticated request to pass return } # Check authentication mode selected in previous HTTP_REQUEST event if {[lindex $AUTHENTICATION_MODE 0] equals "certificate"} { if { [SSL::cert count] <= 0 } { # if there is no client certificate hold the HTTP request till the SSL re-negotiation is done. HTTP::header insert "clientless-mode" 1 HTTP::collect SSL::session invalidate SSL::authenticate always SSL::authenticate depth 9 SSL::cert mode require SSL::renegotiate } elseif {[info exists sessionid]} { # the previous HTTP request in the same TCP connection is already authenticated and session cookie is missing, Insert MRHSession HTTP::cookie insert name MRHSession value $apm_sessionid } else { # SSL client is already authenticated, but Access session not evaluated. enable clientless mode HTTP::header insert "clientless-mode" 1 } } } when ACCESS_SESSION_STARTED { # catch session ID for next requests in the same TCP connection set apm_sessionid [ACCESS::session sid] # extract CN from subject and set in session.logon.last.username variable if {[lindex $AUTHENTICATION_MODE 0] equals "certificate"} { # Allow comma and = to be included in subject. remove space at the end or beginning of strings. set subject [ split [string map {"\\," "," " , " "|" ", " "|" " ," "|" "," "|" "\\=" "=" " = " "|" "= " "|" " =" "|" "=" "|"} [X509::subject [SSL::cert 0]]] "|"]; array set subject_list $subject if {[info exists subject_list(CN)]} { ACCESS::session data set session.logon.last.cn $subject_list(CN) ACCESS::session data set session.logon.last.username $subject_list(CN) ACCESS::session data set session.logon.last.logonname $subject_list(CN) } ACCESS::session data set session.logon.last.upn [findstr [ACCESS::session data get session.ssl.cert.x509extension] "othername:UPN<" 14 ">"] } }
- C_AngNimbostratus
Hi Stanislas,
I have a situation that might be able to use this, but we do have an On-Demand Certificate Authentication in our APM policy. We now have a requirement to connect to this VIP on a specific URL for a SOAP-based web service. Unfortunately, the POST method with the SOAP payload is encountering the 302 redirects to /my.policy. By the time it gets to back to the original SOAP endpoint, the request has become a GET and the payload is no longer being transmitted.
Also, we are trying to do this with mutual TLS, but because of the On-Demand Certificate Authentication, the client certificate is not requested until at least the 3rd redirect (the one with my.policy?nonce=?????). Is there no way around this?
Thanks in advance for any direction you might be able to point me towards,
Charlie
- Stanislas_Piro2Cumulonimbus
This code usage is to not add a On-Demand Certificate Authentication box but only a Client Cert Inspection box. This irule manage the certificate request.
If you add a On-Demand Certificate Authentication box, it breaks the clientless mode.
- jkreyes_313300Nimbostratus
Thanks. What if you just want to allow this for specific users? For example, allow a certain Common Name based on the client certificate supplied?
- Stanislas_Piro2Cumulonimbus
@jkreyes : This code manage clientless authentication for APM and import CN in session.logon.last.cn variable.
you can filter in APM based on this variable.
- C_AngNimbostratus
@stanislas. Thank you for the clarification. I am a little late getting back to you, but our F5 folks decided it was too clunky to squeeze both use-cases (requiring on-demand client cert and MTLS for web services) onto the same Virtual Server. So we are going with an HAProxy or a separate VIP.
- antec42Altostratus
Picking up an old thread here maybe, but I have a use case for this but I also need to split the VIP into a layered VS.
I do the SSL stuff in the terminating LTM Vs and the APM part in the second Vs (to which I pass the traffic with the "virtual <apm_vs>" line in the LTM Vs. The reason for this is that I need to alter some responses that I do not see from APM if they are on the same Vs.
Anyway, when I'm doing this the SSL gets terminated on the LTM vs and I can not do the certificate checks in APM as I normally could. I'm trying a solution where I pass the client certificate on to APM by inserting it as a header into the HTTP traffic on the LTM vs, so that I could pick it up on the APM vs. It works to some extent (I can pass CN, Subject string etc properly) but when I try to pass the whole "[X509::whole [SSL::cert 0]]" and insert it with ACCESS::session data set session.ssl.cert.whole it fails. The set command seems to truncate the certificate or can not handle certain characters in the PEM cert. Does anyone has a clue to what I can do?