cancel
Showing results for 
Search instead for 
Did you mean: 

Help with IRule Client Auth Certs

Mr_Moody
Nimbostratus
Nimbostratus

I have an IRule below that I'm working on. My intent is to enforce client certificate authentication on two URI's only and if any client certificate errors should result in a redirect to a custom error page. The VS has a SSL profile set to 'ignore' client certificates. This rule successfully processes the first two 'If' statements. The problem is that the custom error page is not displayed. Any help would be appreciated.

 

when HTTP_REQUEST { if { not ([HTTP::uri] starts_with "/uri1") || ([HTTP::uri] starts_with "/uri2")} { return } else { if { ([HTTP::uri] starts_with "/uri1") || ([HTTP::uri] starts_with "/uri2")} { SSL::session invalidate     SSL::authenticate always     SSL::authenticate depth 9     SSL::cert mode require     set cmd "SSL::profile /Common/require_clientssl"     eval $cmd     SSL::renegotiate   } else { if {[SSL::verify_result] == 0 }{ return   } else { HTTP::respond 302 Location "http://error.com/error.html" Cache-Control No-Cache Pragma No-Cache } } } }

 

I have another rule that meets two of the three requirements. With the VS SSL profile set to 'request' client certs. This rule does provide a custom error page when Cert errors occur on the two named URI's. But it also results in a certificate prompt for users who access other URI's due to the default SSL profile setting.

 

when HTTP_REQUEST { if { not ([HTTP::uri] starts_with "/uri1") || ([HTTP::uri] starts_with "/uri2")} { return } else { if {[SSL::verify_result] == 0 }{ return   } else { HTTP::respond 302 Location "http://error.com/error.html" Cache-Control No-Cache Pragma No-Cache } } }

 

1 ACCEPTED SOLUTION

Simon_Blakely
F5 Employee
F5 Employee

Your HTTP::respond 302 is in the else clause of your second if statement.

It is never reached.

when HTTP_REQUEST { if { not ([HTTP::uri] starts_with "/uri1") || ([HTTP::uri] starts_with "/uri2")} { # This path has no client-authentication return } else { # perform client-authentication if the uri matches if { ([HTTP::uri] starts_with "/uri1") || ([HTTP::uri] starts_with "/uri2")} { SSL::session invalidate SSL::authenticate always SSL::authenticate depth 9 SSL::cert mode require set cmd "SSL::profile /Common/require_clientssl" eval $cmd SSL::renegotiate } else { # we cannot execute this path because of the first *if* statement if {[SSL::verify_result] == 0 }{ return } else { HTTP::respond 302 Location "http://error.com/error.html" Cache-Control No-Cache Pragma No-Cache } } } }

Try something like

 

when HTTP_REQUEST { if { not ([HTTP::uri] starts_with "/uri1") || ([HTTP::uri] starts_with "/uri2")} { # we don't need to renegotiate with client-authentication return } else { # we do need to renegotiate with client-authentication SSL::session invalidate SSL::authenticate always SSL::authenticate depth 9 SSL::cert mode require set cmd "SSL::profile /Common/require_clientssl" eval $cmd SSL::renegotiate # check if renegotiation with client-auth succeeded if {[SSL::verify_result] == 0 }{ return } else { HTTP::respond 302 Location "http://error.com/error.html" Cache-Control No-Cache Pragma No-Cache } } }

but I haven't tested this to check ...

View solution in original post

2 REPLIES 2

Simon_Blakely
F5 Employee
F5 Employee

Your HTTP::respond 302 is in the else clause of your second if statement.

It is never reached.

when HTTP_REQUEST { if { not ([HTTP::uri] starts_with "/uri1") || ([HTTP::uri] starts_with "/uri2")} { # This path has no client-authentication return } else { # perform client-authentication if the uri matches if { ([HTTP::uri] starts_with "/uri1") || ([HTTP::uri] starts_with "/uri2")} { SSL::session invalidate SSL::authenticate always SSL::authenticate depth 9 SSL::cert mode require set cmd "SSL::profile /Common/require_clientssl" eval $cmd SSL::renegotiate } else { # we cannot execute this path because of the first *if* statement if {[SSL::verify_result] == 0 }{ return } else { HTTP::respond 302 Location "http://error.com/error.html" Cache-Control No-Cache Pragma No-Cache } } } }

Try something like

 

when HTTP_REQUEST { if { not ([HTTP::uri] starts_with "/uri1") || ([HTTP::uri] starts_with "/uri2")} { # we don't need to renegotiate with client-authentication return } else { # we do need to renegotiate with client-authentication SSL::session invalidate SSL::authenticate always SSL::authenticate depth 9 SSL::cert mode require set cmd "SSL::profile /Common/require_clientssl" eval $cmd SSL::renegotiate # check if renegotiation with client-auth succeeded if {[SSL::verify_result] == 0 }{ return } else { HTTP::respond 302 Location "http://error.com/error.html" Cache-Control No-Cache Pragma No-Cache } } }

but I haven't tested this to check ...

Thank you that was it! I also had to change the cert mode to 'request'.