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 ">"]

    }
}
Published Nov 23, 2017
Version 1.0

Was this article helpful?

6 Comments

  • C_Ang's avatar
    C_Ang
    Icon for Nimbostratus rankNimbostratus

    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

     

  • 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.

     

  • 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?

     

  • @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_Ang's avatar
    C_Ang
    Icon for Nimbostratus rankNimbostratus

    @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.

     

  • 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?