For more information regarding the security incident at F5, the actions we are taking to address it, and our ongoing efforts to protect our customers, click here.

Forum Discussion

caz's avatar
caz
Icon for Nimbostratus rankNimbostratus
Apr 15, 2024

Disacard SSL::cert mode to ignore when default SSLClient profile is set to request or require

My need: I want to have one unique VIP to handle both non-secure traffic for UI service and also to secure API services.

For the API, I have 2 cases:

  1. jwt is provided, I need to have the SSL::cert mode to require only if I have clientId in the claims (I have the logic to handle this already), if no clientId in the claims, I need to have the SSL::cert mode to ignore.
  2. jwt is not provided, I need to have SSL::cert mode to require.

 

In F5 I have a sslClientProfile set to request or require and I would like to set it to ignore on a certain condition (URL path based). When doing so in an iRule, it doesn't work to me. I found no way to make the SSL::cert mode ignore to work.

I tried to do the opposite, setting the sslClientProfile to ignore in F5 and elevate the SSL::cert mode to request or ignore depending on my need, but when doing so, the certificates I pass in the query are not taken and I can't add them in a Header.

 

Here's what I tried with the F5's sslClientProfile set to ignore:

when HTTP_REQUEST {
  if { [HTTP::header exists "Authorization"] } {
    if { ([HTTP::header value Authorization] starts_with "Bearer ") } {
      set jwt_header_b64_url [string range [getfield [HTTP::header value Authorization] "." 1] 7 end]
      set jwt_body_b64_url [getfield [HTTP::header value Authorization] "." 2]
      set jwt_sig_b64_url [getfield [HTTP::header value Authorization] "." 3]

      if { $jwt_header_b64_url ne "" and  $jwt_body_b64_url ne "" and $jwt_sig_b64_url ne "" } {
        set jwt_header [call b64url_decode $jwt_header_b64_url]
        set jwt_body [call b64url_decode $jwt_body_b64_url]
        set jwt_sig [call b64url_decode $jwt_sig_b64_url]

        if { $jwt_header ne "" and $jwt_body ne "" and $jwt_sig ne ""} {
          set jwt_clientId [call get_json_str "clientId" $jwt_body]

          if {[string trim $jwt_clientId] ne ""} {
            if { [SSL::cert count] <= 0 } {
              HTTP::collect
              SSL::authenticate always
              SSL::authenticate depth 9
              SSL::cert mode require
              SSL::renegotiate
            }
          }
        }
      }
    }
  }

  if { [HTTP::uri] matches_regex {/auth|/.*/.*/.*/auth/.*|/.*/ua-ui/.*|/favicon.ico|/federation.*|/f5/health} } {
    set uri [regsub -nocase {/.*/.*/.*/auth/} [HTTP::uri] "/auth/"]
    HTTP::uri $uri
  } else {
    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 } {
      set thecert [X509::whole [SSL::cert 0]]
      HTTP::header insert "HTTP_HEADER_CLIENT_CERT" [X509::whole [SSL::cert 0]]
      HTTP::header insert "X-SSL-Client-Cert-S-Dn" [X509::subject [SSL::cert 0]]
      HTTP::header insert "X-SSL-Client-Cert-I-Dn" [X509::issuer [SSL::cert 0]]
      set sslresult [X509::verify_cert_error_string [SSL::verify_result]]
      HTTP::header insert "X-SSL-Client-Cert-Verify" [string map -nocase {"ok" "success"} $sslresult]
    } else {
      if { [HTTP::header exists "HTTP_HEADER_CLIENT_CERT"] } {
        HTTP::header replace "HTTP_HEADER_CLIENT_CERT" ""
      }
      HTTP::header insert "HTTP_HEADER_CLIENT_CERT" ""
    }
  }
}

 

I tried to reverse the logic but I couldn't get it work.

Is there another way to handle the downgrade of SSL::cert mode to ignore?

 

Note: I tried also something proposed in Requiring an SSL Certificate for Parts of an Application | DevCentral with no luck...

2 Replies

  • In the HTTP_REQUEST event, we check if the clientId exists in the JWT claims. If it does, we require an SSL certificate. Otherwise, we ignore it. The URL path-based logic ensures that specific paths are handled differently. In the HTTP_REQUEST_SEND event, we handle the client certificate details. 

    • caz's avatar
      caz
      Icon for Nimbostratus rankNimbostratus

      Thanks for the insight, any chance you share your irule logic?