Forum Discussion

Edgar_Palamarch's avatar
Edgar_Palamarch
Icon for Nimbostratus rankNimbostratus
Oct 14, 2015

Client Authentication Based On URI

Hello,

Currently, to configure client authentication on a URI, we create 2 client SSL profiles (one of which is parent for the other) and 2 iRules that check a data group against the URI list. The client SSL profile (not parent) is attached to virtual server on secure port along with the iRule. The second iRule is checking for the URI in the data group and redirects to https:// and is attached to the non-secure virtual server.

Parent SSL profile is configured with certificate bundle in Client Authentication for both Trusted Certificate Authorities and Advertised Certificate Authorities.

Everything works as expected, but looks complex. I have a feeling the above setup could be put into just one iRule without even having a data group created since there is only one URI that needs to be secured with the client authentication.

I have used the iRule from https://devcentral.f5.com/articles/selective-client-cert-authentication but can't make it work.

when CLIENTSSL_CLIENTCERT {
  HTTP::release
  if { [SSL::cert count] < 1 } {
    reject
  }
}

when HTTP_REQUEST {
  if { [HTTP::uri] contains [string tolower "/secureapi"] } {
    if { [SSL::cert count] <= 0 } {
      HTTP::collect
      SSL::authenticate always
      SSL::authenticate depth 9
      SSL::cert mode require
      SSL::renegotiate
    }
  }
}

when HTTP_REQUEST_SEND {
  clientside {
    if { [SSL::cert count] > 0 } {
      HTTP::header insert "X-SSL-Session-ID"        [SSL::sessionid]
      HTTP::header insert "X-SSL-Client-Cert-Status"    [X509::verify_cert_error_string [SSL::verify_result]]
      HTTP::header insert "X-SSL-Client-Cert-Subject"   [X509::subject [SSL::cert 0]]
      HTTP::header insert "X-SSL-Client-Cert-Issuer"    [X509::issuer [SSL::cert 0]]
    }
  }
} 

Thanks for your time and help!

7 Replies

  • That code actually just works on a single VIP. You just need the one client SSL profile that also has the Trusted Certificate Authorities option configured and Client Authentication set to "ignore". When the browser accesses the secure site URL, the iRule is forcing an SSL renegotiation and flipping the Client Authentication setting to "require".

     

    • iamsajjad's avatar
      iamsajjad
      Icon for Cirrus rankCirrus

      Your expert feedback was helpful to implement similar conditional mTLS with confidence in 2023!

      In another article you nicely explained purpose of HTTP:collect. 1) I wonder why do we need HTTP:release? 2) Does it matter calling it at the beginning or end? 3) I don't good explanation. I found without this piece HTTP_REQUEST_SEND does not fire.

      Also, while we are renegotiation anyway 1) should we invalidate the ssl session? 2) What value it adds? 3) Otherwise, what's the pitafall not invalidating the session?

      Will aprpeciate your response.

      Thank you.

  • Does this iRule require the client cert configured for that /secureApi folder on the web servers then?

     

    It does not. In fact you probably don't want to try to do client cert auth at the web servers at all.

     

    Also, would this iRule work with a cert bundle configured for the Trusted Certificate Authorities option?

     

    You absolutely need a Trusted Certificate Authorities bundle applied to the client SSL profile for mutual authentication to work. It won't be referenced until you actually renegotiate the SSL session and request a certificate from the client.

     

    I have configured the client profile with one cert and am getting ERR_CONNECTION_RESET.

     

    One cert? Are you talking about the certificate and private key selection in the top of the client SSL profile?

     

  • You don't use a client cert in the trust bundle. The bundle needs to contain all of the certificate authority certificates that make up the "trust path" from the client's certificate to the self-signed root. So for example, if the PKI looks like this:

    client cert  ->  subordinate CA  ->  root CA
    

    then the trust bundle must include the subordinate and root CA certs.

  • The client will present a client certificate. The client SSL profile must just a) request a client certificate, and b) validate that client certificate.

     

    The first (requesting a client certificate) is handled with the Client Certificate option under the Client Authentication section of the client SSL profile. Set it Require if you want to request a client certificate in the SSL handshake, but fail closed if they don't send one. Set it to Request if you want to request a client certificate in the SSL handshake, but fail open if they don't send one.

     

    The second (validating the client certificate) is handled by the Trusted Certificate Authorities option also in the Client Authentication section. This needs to be a CA certificate, or bundle of CA certificates that the BIG-IP needs to establish a trust chain from the client's certificate all the way to the self-signed root CA.

     

  • earlier you wrote that the client SSL profile should have the Client Authentication set to "ignore" and the iRule will flip it to "Require" when the secure URI is accessed.

    I did indeed forget the context of the original question. 😉 But yet, because you're flipping that bit in the iRule, the Client Authentication option should be set to Ignore.

    Also, it looks like the iRule doesn't detect the URI and the /SecureApi path is accessible, no browser pop-up requesting the client cert.

    Well first, you're looking for an exact match against "/myApp/secureapi/myPage". At the very least I'd probably do a "starts_with" and include the base directory for which you want to require a client certificate.

    if { [string tolower [HTTP::uri]] starts_with "/myapp/secureapi" }
    
  • Interesting. I probably should have asked which BIG-IP version you're using. In any case, the above iRule appears to work in 11.6 and 12.0. Also, the SSL::renegotiate wiki page has a slightly different version of that iRule that you might want to try:

     

    https://devcentral.f5.com/wiki/iRules.SSL__renegotiate.ashx

     

    It uses the CLIENTSSL_HANDSHAKE event instead of the CLIENTSSL_CLIENTCERT event.