cancel
Showing results for 
Search instead for 
Did you mean: 

iRule to Insert Client Cert into HTTP Header only when Certificate is from certain Root CA

Vasil_Genov
Altostratus
Altostratus

Hello Group,

 

My curent setup is as follows:

I have a HTTPS VS with Clinet SSL profile that has Client Authentication set to Request with Trusted CA and Advertised CA set to appropriate CA.

What I need to achieve is to insert the client Cert into the HTTP Header with the following conditions:

1) If there is no client Cert in the request, LTM should simply establish the connection.

2) If there is a client cert and it is signed by the Trunster CA, I should inser the ssl cert in X-Client-Cert and establish the connection.

3) If there is a client cert and it is not signed by the Trunster CA, I should reject the connetion.

4) if the reqest alredy has a X-Client-Cert header, I should drop the connection.

 

I do not have much experience in creating iRules but thied something like this:

when RULE_INIT {

    set static::debug 1

}

 

when CLIENTSSL_CLIENTCERT {

    set subject_dn [X509::subject [SSL::cert 0]]

    if { $subject_dn != "" }{

        if { $static::debug }{ log "Client Certificate received: $subject_dn"}

    }

}

when HTTP_REQUEST {

    if { ($subject_dn contains "CN=blah-blah") } {

HTTP::header insert X-Client-Cert [b64encode [SSL::cert 0]]

    }

    else {

    continue

    }

}

 

Needless to say, it did not work 😄

Scenarios 1) and 4) returned „SSL_connect: Connection reset by peer in connection to test-site:443“

Scenarios 2) adn 3) returned „SSL_read: Connection reset by peer, errno 54“

 

Any suggestions would be great.

Thanks in advance!

1 ACCEPTED SOLUTION

Vasil_Genov
Altostratus
Altostratus

I modified the rule and also added a check for existing x-client-cert. Now it seem to work.

when RULE_INIT {

  set static::org "O=MON"

}

 

when CLIENTSSL_CLIENTCERT {

if {[SSL::cert 0] eq ""}{

  return

  }

else {

set issuer_dn [X509::issuer [SSL::cert 0]]

log "Client Certificate Received: $issuer_dn"

if { ($issuer_dn contains $static::org) } {

log "Client Certificate Accepted: $issuer_dn"

}

else {

log "No Matching Client Certificate Was Found Using: $issuer_dn"

reject

}

}

}

 

when HTTP_REQUEST {

foreach header_name [HTTP::header names] {

if {[string match -nocase x-client-cert $header_name]}{

HTTP::header remove $header_name

  }

  }

   HTTP::header insert X-Client-Cert [b64encode [SSL::cert 0]]  

}

 

I am leaving the full rule here, so if anyone need something similar, it can be used.

View solution in original post

2 REPLIES 2

Vasil_Genov
Altostratus
Altostratus

I updated the iRule as follows:

when RULE_INIT {

  set static::org "OU=<neededOU>"

}

 

when CLIENTSSL_CLIENTCERT {

if {[SSL::cert 0] eq ""}{

  return

  }

else {

set subject_dn [X509::subject [SSL::cert 0]]

log "Client Certificate Received: $subject_dn"

if { ($subject_dn contains $static::org) } {

log "Client Certificate Accepted: $subject_dn"

}

else {

log "No Matching Client Certificate Was Found Using: $subject_dn"

reject

}

}

}

 

when HTTP_REQUEST {

  HTTP::header insert X-Client-Cert [b64encode [SSL::cert 0]]

}

 

Now I get somehow mixed results -

1 is OK

2 is OK

3 is Kinda OK - connection is reset

4 is not OK (which at time point is obvious as I am not actually trying to correct it - I want to get first 3 working first)

 

So what Is left is how to check if there is already and inserted spoofed X-Client-Cert in the header.

Any suggestions?

 

Vasil_Genov
Altostratus
Altostratus

I modified the rule and also added a check for existing x-client-cert. Now it seem to work.

when RULE_INIT {

  set static::org "O=MON"

}

 

when CLIENTSSL_CLIENTCERT {

if {[SSL::cert 0] eq ""}{

  return

  }

else {

set issuer_dn [X509::issuer [SSL::cert 0]]

log "Client Certificate Received: $issuer_dn"

if { ($issuer_dn contains $static::org) } {

log "Client Certificate Accepted: $issuer_dn"

}

else {

log "No Matching Client Certificate Was Found Using: $issuer_dn"

reject

}

}

}

 

when HTTP_REQUEST {

foreach header_name [HTTP::header names] {

if {[string match -nocase x-client-cert $header_name]}{

HTTP::header remove $header_name

  }

  }

   HTTP::header insert X-Client-Cert [b64encode [SSL::cert 0]]  

}

 

I am leaving the full rule here, so if anyone need something similar, it can be used.