Forum Discussion

bcarreker's avatar
bcarreker
Icon for Cirrus rankCirrus
Jun 03, 2020

Passing PKI Certificate as "base64encode"

I am trying to create an iRule for an app service, so that it authenticates traffic on the context path and passes the PKI certificate as "base64encode" in the "sslclientcert64" header sent to the app service.

 

(Please see attachment) I've taken the base64 script found on Devcentral, and added an "when HTTP_REQUEST" line, so that when "/tsmats_tools" is added to the URL, the iRule goes into effect. Unfortunately, this results in a 403 FORBIDDEN.

 

Is there anything else I can do on my end?

1 Reply

  • Here's the iRule I'm using:

     

    # client_cert_header_insert_rule

     

    when CLIENTSSL_CLIENTCERT {

     

      # Check if client presented at least one cert

      if {[SSL::cert count] > 0}{

     

         # Insert the following fields in the session table with a timeout of 7200 seconds:

         #  Do the processing now as opposed to in HTTP_REQUEST as there

         #  can be many HTTP requests using the same SSL session ID

         #

         #  Index - item

         #  0 - base64 encoding of the client SSL cert

         #  1 - serial number of the cert

         #  2 - the verification status text for the client cert against the client SSL profile's root CA cert

         session add ssl [SSL::sessionid] [list \

            [SSL::verify_result] \

            [b64encode [SSL::cert 0]] \

            [X509::serial_number [SSL::cert 0]] \

         ] 7200

     

         log local0. "[IP::client_addr]:[TCP::client_port]: Added session data for cert. Status:\

            [X509::verify_cert_error_string [lindex [session lookup ssl [SSL::sessionid]] 0]] with key [SSL::sessionid]"

      }

    }

     

    when HTTP_REQUEST {

     

      if {[string tolower [HTTP::host]] equals "URL goes here" and [string tolower [HTTP::uri]] equals "URI goes here" } {

     

       HTTP::header replace Host "Back end service goes here"

      # Check if SSL session ID is in the cache (SSL::sessionid returns 64 zeroes if it's not in v9 and a null string in v10)

      if {[SSL::sessionid] ne "0000000000000000000000000000000000000000000000000000000000000000" && [SSL::sessionid] ne ""}{

     

         # Get the session table entry (a TCL list) for this session ID

         set session_data [session lookup ssl [SSL::sessionid]]

     

         # Check if the first element of the session table entry for this session ID is 0 (status for successful cert validation)

         if {[lindex $session_data 0] == 0}{

     

            log local0. "[IP::client_addr]:[TCP::client_port]: Valid cert per session table entry. Inserting cert details in HTTP headers."

     

            # Insert cert details in the HTTP headers

            HTTP::header insert SSLClientCertStatus "ok"

            HTTP::header insert SSLClientCertb64 [lindex $session_data 1]

            HTTP::header insert SSLClientCertSN [lindex $session_data 2]

     

            # Exit this event in this rule

            return

         }

      }

      # If we're still in this rule, cert wasn't valid

      #  so send HTTP 302 redirect to an error page

      HTTP::respond 302 Location "http://[HTTP::host]/cert_error.html"

     

      log local0. "[IP::client_addr]:[TCP::client_port]: No or invalid cert from client."

    }

    }