Forum Discussion
Ted_51200
Nimbostratus
Apr 14, 2008Client SSL Cert Irule
I am looking to request a client ssl cert to happen only if a a spacific url is requested but ignore if not.
My Irule
when CLIENTSSL_CLIENTCERT {
set the_cert [SSL::cert 0]
set subject_dn [X509::subject $the_cert]
if { $subject_dn != "" }{
if { $debug }{ log "Client Certificate received: $subject_dn"}
}
}
when HTTP_REQUEST {
if { [HTTP::uri] starts_with "/secure/" } {
log "Certificate required for: [HTTP::uri]"
if { [SSL::cert count] == 0} {
log "Certificate not present. Passing to Login .....: [HTTP::uri]"
SSL::cert mode require
SSL::renegotiate
pool pool_xx
}
set pkiSubject [X509::subject $the_cert]
set pkiIssuer [X509::issuer $the_cert]
HTTP::header insert CLIENTSSL_Status [SSL::verify_result]
HTTP::header insert CLIENTSSL_StatusString [X509::verify_cert_error_string [SSL::verify_result]]
HTTP::header insert CLIENTSSL_CN $pkiSubject
HTTP::header insert CLIENTSSL_SSLIssuer $pkiIssuer
HTTP::header insert CLIENTSSL_SSLClientCertSN [X509::serial_number $the_cert]
}
}
6 Replies
- Ted_51200
Nimbostratus
when i go into the Local Traffic / Client SSL Profiles / EXTCLIENTSSL Profile
and set Client Authentication / Client Certificateit to ignore i lose the client cert field.. and as per my request above i want it to ignore until that /secure/~ is hit then request...
Please help devcental... your my only hope =) - Stephen_Archer_Historic F5 AccountI've been trying to do a similar thing... and am also having problems. All I'm trying to do is to check a URI, and if it contains '/SecureURI', then perform client authentication, and if authorised (using the SOA_Trusted_Certs , forward to the secure pool using a serverSSL profile. If unauthorised, reject the connection.
If the URI does not contain '/SecureURI', then forward to the regular HTTP pool, and disable the serverSSL profile. When I test the iRule below, by trying to access the insecure site, it works, however when I try the secure URI, I get this error: "HTTP_REQUEST - cant read subject_dn: no such variable while executing matchclass $subject_dn contains $::SOA_Trusted_Certs"
Here is the iRule:
when RULE_INIT {
set ::org "O=MyCompany"
}
when CLIENTSSL_CLIENTCERT {
set subject_dn [X509::subject [SSL::cert 0]]
log "Client Certificate Received: $subject_dn"
}
when HTTP_REQUEST {
if {[HTTP::uri] contains "/SecureURI"} {
pool secure_pool_443
if { ([matchclass $subject_dn contains $::SOA_Trusted_Certs]) and ($subject_dn contains $::org) } {
log "Client Certificate Accepted: $subject_dn"
} else {
log "No Matching Client Certificate Was Found Using: $subject_dn"
reject
}
}
else {
pool unsecure_pool_80
SSL::disable serverside
}
}
Kircos, what error do you see when the iRule is hit? - Ted_51200
Nimbostratus
I now have a working Irule, but only sends the SSL headers/Info on refresh... anyone have any idea why ? or how to correct it?
Irule:
when CLIENTSSL_CLIENTCERT {
log local0. "start CLIENTSSL_CLIENTCERT"
set the_cert [SSL::cert 0]
set pkiSubject [X509::subject $the_cert]
set pkiIssuer [X509::issuer $the_cert]
HTTP::release
log local0. "end CLIENTSSL_CLIENTCERT"
}
when HTTP_REQUEST_SEND {
clientside {
log local0. "start HTTP_REQUEST_SEND"
if { [SSL::cert count] > 0} {
set the_cert [SSL::cert 0]
set pkiSubject [X509::subject $the_cert]
set pkiIssuer [X509::issuer $the_cert]
HTTP::header replace CLIENTSSL_Status [SSL::verify_result]
HTTP::header replace CLIENTSSL_StatusString [X509::verify_cert_error_string [SSL::verify_result]]
HTTP::header replace CLIENTSSL_CN $pkiSubject
HTTP::header replace CLIENTSSL_SSLIssuer $pkiIssuer
HTTP::header replace CLIENTSSL_SSLClientCertSN [X509::serial_number $the_cert]
HTTP::header replace CLIENTSSL_Cert [b64encode $the_cert]
log local0. "end HTTP_REQUEST_SEND"
}
}
}
when HTTP_REQUEST {
log local0. "start HTTP_REQUEST"
if { [HTTP::uri] starts_with "/SLFCSSOCollector/ssl/" } {
if { [SSL::cert count] == 0} {
SSL::cert mode require
SSL::renegotiate
log local0. "end HTTP_REQUEST"
}
}
} - Nicolas_Menant
Employee
Hi,
I don't understand why you use HTTP::release in your CLIENT_SSL event.
can't you do this with this code? :when CLIENTSSL_CLIENTCERT { log local0. "start CLIENTSSL_CLIENTCERT" set the_cert [SSL::cert 0] set pkiSubject [X509::subject $the_cert] set pkiIssuer [X509::issuer $the_cert] log local0. "end CLIENTSSL_CLIENTCERT" } when HTTP_REQUEST { log local0. "start HTTP_REQUEST, uri is [HTTP::uri]" if { [HTTP::uri] starts_with "/SLFCSSOCollector/ssl/" } { log local0. "URI /SLFCSSOCollector/ssl/ detected!" if { [SSL::cert count] == 0} { log local0. "no certificate found... force SSL" SSL::cert mode require SSL::renegotiate log local0. "end HTTP_REQUEST" } } else { log local0. "certificate found!" set the_cert [SSL::cert 0] set pkiSubject [X509::subject $the_cert] set pkiIssuer [X509::issuer $the_cert] HTTP::header insert CLIENTSSL_Status [SSL::verify_result] HTTP::header insert CLIENTSSL_StatusString [X509::verify_cert_error_string [SSL::verify_result]] HTTP::header insert CLIENTSSL_CN $pkiSubject HTTP::header insert CLIENTSSL_SSLIssuer $pkiIssuer HTTP::header insert CLIENTSSL_SSLClientCertSN [X509::serial_number $the_cert] HTTP::header insert CLIENTSSL_Cert [b64encode $the_cert] } }
If you test this code, please show us the output of /var/log/ltm so that we can trace what is happening - Ted_51200
Nimbostratus
im now using the following irule
when CLIENTSSL_CLIENTCERT {
log local0. "start CLIENTSSL_CLIENTCERT"
set the_cert [SSL::cert 0]
set pkiSubject [X509::subject $the_cert]
set pkiIssuer [X509::issuer $the_cert]
log local0. "end CLIENTSSL_CLIENTCERT"
}
when HTTP_REQUEST {
log local0. "start HTTP_REQUEST, uri is [HTTP::uri]"
if { [HTTP::uri] starts_with "/SLFCSSOCollector/ssl/" } {
log local0. "URI /SLFCSSOCollector/ssl/ detected!"
if { [SSL::cert count] == 0} {
log local0. "no certificate found... force SSL"
SSL::cert mode require
SSL::renegotiate
log local0. "end HTTP_REQUEST"
} else {
log local0. "certificate found!"
set the_cert [SSL::cert 0]
set pkiSubject [X509::subject $the_cert]
set pkiIssuer [X509::issuer $the_cert]
HTTP::header insert CLIENTSSL_Status [SSL::verify_result]
HTTP::header insert CLIENTSSL_StatusString [X509::verify_cert_error_string [SSL::verify_result]]
HTTP::header insert CLIENTSSL_CN $pkiSubject
HTTP::header insert CLIENTSSL_SSLIssuer $pkiIssuer
HTTP::header insert CLIENTSSL_SSLClientCertSN [X509::serial_number $the_cert]
HTTP::header insert CLIENTSSL_Cert [b64encode $the_cert]
}
}
}
I am still having the info not come accross in the first header have to hit F5(refresh) then after headers show up... Here is my logs
12:28:31 EDT 2008Rule sslheader : start HTTP_REQUEST, uri is /SLFCSSOCollector/ssl/headers.asp
12:28:31 EDT 2008Rule sslheader : URI /SLFCSSOCollector/ssl/ detected!
12:28:31 EDT 2008Rule sslheader : no certificate found... force SSL
12:28:31 EDT 2008Rule sslheader : end HTTP_REQUEST
12:28:33 EDT 2008Rule sslheader : start HTTP_REQUEST, uri is /SLFCSSOCollector/ssl/headers.asp
12:28:33 EDT 2008Rule sslheader : URI /SLFCSSOCollector/ssl/ detected!
12:28:33 EDT 2008Rule sslheader : no certificate found... force SSL
12:28:33 EDT 2008Rule sslheader : end HTTP_REQUEST
12:28:33 EDT 2008Rule sslheader : start CLIENTSSL_CLIENTCERT
12:28:33 EDT 2008Rule sslheader : end CLIENTSSL_CLIENTCERT
12:28:35 EDT 2008Rule sslheader : start HTTP_REQUEST, uri is /SLFCSSOCollector/ssl/headers.asp
12:28:35 EDT 2008Rule sslheader : URI /SLFCSSOCollector/ssl/ detected!
12:28:35 EDT 2008Rule sslheader : certificate found!
12:28:37 EDT 2008Rule sslheader : start HTTP_REQUEST, uri is /SLFCSSOCollector/ssl/headers.asp
12:28:37 EDT 2008Rule sslheader : URI /SLFCSSOCollector/ssl/ detected!
12:28:37 EDT 2008Rule sslheader : no certificate found... force SSL
12:28:37 EDT 2008Rule sslheader : end HTTP_REQUEST
12:28:52 EDT 2008Rule sslheader : start HTTP_REQUEST, uri is /SLFCSSOCollector/ssl/headers.asp
12:28:52 EDT 2008Rule sslheader : URI /SLFCSSOCollector/ssl/ detected!
12:28:52 EDT 2008Rule sslheader : no certificate found... force SSL
12:28:52 EDT 2008Rule sslheader : end HTTP_REQUEST - Nicolas_Menant
Employee
Ok Thanks for your logging details !!
I checked the wiki and it seems you need to do an HTTP::collect ... i'm unsure why but rules1: Devcentral's wiki should be trusted 😄when CLIENTSSL_HANDSHAKE { log local0. "client SSL Handshake" if { [SSL::cert count] > 0 } { log local0. "client SSL Handshake...HTTP released" HTTP::release } } when CLIENTSSL_CLIENTCERT { log local0. "start CLIENTSSL_CLIENTCERT" set the_cert [SSL::cert 0] set pkiSubject [X509::subject $the_cert] set pkiIssuer [X509::issuer $the_cert] log local0. "end CLIENTSSL_CLIENTCERT" } when HTTP_REQUEST { log local0. "start HTTP_REQUEST, uri is [HTTP::uri]" if { [HTTP::uri] starts_with "/SLFCSSOCollector/ssl/" } { log local0. "URI /SLFCSSOCollector/ssl/ detected!" if { [SSL::cert count] == 0} { HTTP::collect SSL::authenticate always SSL::authenticate depth 9 log local0. "no certificate found... force SSL" SSL::cert mode require SSL::renegotiate log local0. "end HTTP_REQUEST" } } else { log local0. "certificate found!" set the_cert [SSL::cert 0] set pkiSubject [X509::subject $the_cert] set pkiIssuer [X509::issuer $the_cert] HTTP::header insert CLIENTSSL_Status [SSL::verify_result] HTTP::header insert CLIENTSSL_StatusString [SSL::verify_result]] HTTP::header insert CLIENTSSL_CN $pkiSubject HTTP::header insert CLIENTSSL_SSLIssuer $pkiIssuer HTTP::header insert CLIENTSSL_SSLClientCertSN [X509::serial_number $the_cert] HTTP::header insert CLIENTSSL_Cert [b64encode $the_cert] } }
This way it applies the recommandation from the wiki: Click here
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
DevCentral Quicklinks
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
Discover DevCentral Connects