Forum Discussion

SebScott's avatar
SebScott
Icon for Nimbostratus rankNimbostratus
Sep 08, 2024

Re-execute iRule to read CN value of client cert, but after you know URI.

Hi We have been dealing with a new implementation where we need to either accept or reject access to a certain path/URI of a VIP based on the CN of the client cert.........and for other paths that either don't have a client cert or the CN of a client cert does not match our Data-group allow access to other URIs.

We have a iRule below which works great, but it has to request a user for a client cert in which we only want to do when required to go to the target URIs.  The only way we can get this to work is to have the "request" option enabled in the SSL client profile so it reads the subject under "when CLIENTSSL_CLIENTCERT' which obviously happens before we can read the path under "when HTTP_REQUEST" which is not great as it requests the client using a browser for a client certificate, which is what we want to avoid.   

What we want to do is renegotiate SSL when going to a certain path so only those trying to get to a special path get requested for a client cert and then the subject is read and decision made based on CN of cert as to whether they can get to that path

We have tried to trigger a renegotiate ssl in a Proc, but the problem is we need to read the subject that you can only do in "when CLIENTSSL_CLIENTCERT" and don't know how to do that after a renegotiation ssl.  We thought hat maybe we could restart the whole iRule again from the proc, but don't know how to do that.  Maybe we could call another iRule, but it looks like that is just a proc too and we can't nest "when CLIENTSSL_CLIENTCERT" in anything.   We have asked a TCL guru in our organisation and they are a little stumped too, so any help would be greatly appreciated.

As far as we can tell that can't be nested in a proc or any other stanza.  Maybe there is a better way or there is a simple line of code we are missing.  Here is a our script that does everything we need , but requests human clients using a browser for a client cert.


when RULE_INIT {
   set static::debug 1
}


when CLIENTSSL_CLIENTCERT {
	# Check if client provided a cert
	if {[SSL::cert 0] eq ""}{
        set subject_dn void
		log local0.info "NoCert: $subject_dn"
	 } else {
		#Example Subject DN:  /C=AU/ST=NSW/L=Syd/O=Your Organisation/OU=Your OU/CN=John Smith
		set subject_dn [X509::subject [SSL::cert 0]]
		set client_cert [SSL::cert 0]
		set ssl_client_cert_value [X509::whole $client_cert]
		set client_cert_validated 1
		log local0.info "Client Certificate Accepted: [SSL::cert 0]"
		log local0.info "Client Certificate Received: $subject_dn"
		#Check if the client certificate contains the correct O and a CN from the list
	}
}


when HTTP_REQUEST {
	set httpUri [HTTP::uri]
	switch -glob [HTTP::uri] {
        "/BlahBlah" -
		"/YadaYada/*" {
        
			  ##This is where we want to renegoiate a new SSL profile and read the client cert"
			 
				
			if { [info exists client_cert_validated] and ([matchclass $subject_dn contains API-CN_List]) }  {
				#Accept the client cert
				log local0.info "ClientCertAccepted: $subject_dn"
				return
			} 
			else {
			    log local0.info "nugh 2.1"

                  ###Or here

			}
		}

    	"/FreeForAll" -
		"/NoNeedForCertHere" {     
		 log local0.info "NoCertRequired" 
			return
		}
		default {
		log local0.info "NoMatchingPath" 
		    reject
			return
		}
	}
}

 

  • Thanks I will try that tomorrow and let you know.

     

    I think I may need to add the following to get an alternative client profile to ask for the client cert though.  Is that right?

    .......

            # Redirect to a special URI that will prompt for a client certificate
            HTTP::redirect "/require-cert$httpUri"

        SSL::session invalidate
        SSL::authenticate always
        SSL::authenticate depth 9
        SSL::cert mode require
        set cmd "SSL::profile /Common/ClientSSL-RequireCert-Profile"
        SSL::renegotiate

    return

    ........

    • SebScott's avatar
      SebScott
      Icon for Nimbostratus rankNimbostratus

      Hi.

      I did try this method, but got hit with a few little snags that I think are telling me I can't run these HTTP commands in the CLIENTSSL_CLIENTCERT event.  Although the last line suggests I have not got the syntax right for the variable, which I could fix it is the first 3 lines that suggest I can't make this work because they need to be in the HTTP_REQUEST event, is that correct?

       

       

       

      I am going to try and fire off a subroutine(Proc) to re-initiate the the ssl negotiation against  different client SSL profile and then execute another Irule to trigger the CLIENT_SSL event and subsequent HHTP_REQUEST event which all seems very complicated so open to other simpler suggestions like this previous one from susan789wolf that showed real promise in the simpler logic

       [command is not valid in current event context (CLIENTSSL_CLIENTCERT)][HTTP::redirect $original_uri]
      /Common/API-CNCheck-New-v2:53: error: [command is not valid in current event context (CLIENTSSL_CLIENTCERT)][HTTP::uri]
      /Common/API-CNCheck-New-v2:51: error: [command is not valid in current event context (CLIENTSSL_CLIENTCERT)][HTTP::uri]
      /Common/API-CNCheck-New-v2:3: error: [wrong # args][set static::client_cert_required "/BlahBlah" "/YadaYada/*"]