Forum Discussion

Martín_Cafferat's avatar
Martín_Cafferat
Icon for Nimbostratus rankNimbostratus
Jul 30, 2020

Select clientssl profile based on uri pattern

Hello everyone, I need some help with this scenario. I've found similar questions and suggestions from devcentral memebers but I'm stuck and haven't been able to come up with a solution.

 

I have an API Management solution published through a single Virtual Server in my BigIP. There are several API's present on this solution and I would like to enforce client authentication with SSL\TLS certificates, but requiring a specific certificate depending on which API they will be requesting.

 

In other words, if I have a single VS where I

if the request is to: myapidomain.com/api-companyA, then I want to request the client certificate of Company A

if the request is to: myapidomain.com/api-companyB, , then I want to request the client certificate of Company B

if the request is to: myapidomain.com/general-public-api, then I don't want to use client authentication, just present the server certificate

 

I think that it all comes down to choosing a different clientssl profile based on the uri pattern, but:

  • I can only inspect the http request after the TLS negotation has been completed using the default ssl profile of the VS
  • I cannot use the command to change the ssl profile inside the HTTP REQUEST event

 

I have seen some related questions where they suggest to do something like this. But they are changing the current ssl profile to request client authentication, instead of changing the ssl profile. For testing purposes, I have setup two client ssl profiles, each of them requiring client authentication but using different self signed certificates.

 

when HTTP_REQUEST {

  switch -glob [HTTP::path] {

     "/api-companyA" {

        HTTP::collect

        SSL::session invalidate

        SSL::authenticate always

        SSL::authenticate depth 9

        SSL::cert mode require

        SSL::renegotiate

// Another post suggested using SSL::profile here to change the profile, but it is not allowed inside HTTP REQUEST

     }

     "/api-companyB" {

        HTTP::collect

        SSL::session invalidate

        SSL::authenticate always

        SSL::authenticate depth 9

        SSL::cert mode require

        SSL::renegotiate

     }

  }

}

 

Would it be possible to use a flag variable for this? For example, start with a default value, change it within the HTTP_REQUEST event based on the URI, force an SSL\TLS renegotiation and then in a CLIENT_ACCEPTED event use the value of that variable to set the profile? I tried something like this but it seems that the CLIENT_ACCEPTED method does not fire after the SSL::renegotiate command is issued.

 

when RULE_INIT {

 set ::count 0

}

 

when CLIENT_ACCEPTED {

 if {$::count == 1} {

  SSL::profile profile_with_client_authentication_companyA

 } 

}

 

when HTTP_REQUEST {

 

  switch -glob [HTTP::path] {

   "/supervielledev/public-partners/myloopbackapi" {

     set ::count 1

     SSL::renegotiate

   }

   "/supervielledev/public-partners/myotherloopbackapi" {

     set ::count 2

     SSL::renegotiate

   }

  }

}

 

Thanks in advance.

1 Reply

  • I think you could use a single client SSL profile that accepts either client cert. When the CLIENTSSL_CLIENTCERT event is triggered (before HTTP_REQUEST), you could use SSL::cert to record the client cert in a variable. Then, when the HTTP_REQUEST event is raised, you could check that the URI is correct for the cert you captured earlier.