Forum Discussion

Leszek_Majewsk1's avatar
Leszek_Majewsk1
Icon for Nimbostratus rankNimbostratus
Nov 13, 2007

iRule to require client certificate and validate it

I have limited possibilities to test the iRule because the business application is running via the F5... so can anyone help with this code (if there is no obvious syntax error):

 

 

when HTTP_REQUEST {

 

if { [HTTP::uri] starts_with "/pattern" }

 

{HTTP::collect

 

SSL::cert mode require

 

SSL::renegotiate

 

set ssl_cert [SSL::cert 0]

 

set isMatch 0

 

set org "Company name"

 

set locality "Warszawa"

 

set name "www.f5.com.pl"

 

set country "PL"

 

set issorg "“Thawte Consulting (Pty) Ltd."

 

set isscn "Thawte SGC C"

 

set issctr "PL"

 

set subject_dn [X509::subject $ssl_cert]

 

set issuer_dn [X509::issuer $ssl_cert]

 

log "Client Certificate Received: $subject_dn, $issuer_dn"

 

 

 

if { ($subject_dn matches $org) and ($subject_dn matches $locality) and ($subject_dn matches $name) and ($subject_dn matches $country) and ($issuer_dn matches $issorg) and ($issuer_dn matches $isscn) and ($issuer_dn matches $issctr)}

 

{

 

log "Client Certificate Accepted: $subject_dn, $issuer_dn"

 

set isMatch 1

 

pool TestSSL}

 

if { $isMatch == 0 }

 

{

 

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

 

reject

 

}

 

}

 

else

 

{

 

pool TEST

 

}

 

}

8 Replies

  • Colin_Walker_12's avatar
    Colin_Walker_12
    Historic F5 Account
    What do you mean "help" with this code? Is it not working? How is it behaving? What is it you're trying to accomplish from a big picture?

     

     

    Colin
  • hi,

     

     

    I have just checked that this version (below) is able to compile on F5:

     

     

    when HTTP_REQUEST {

     

    if { [HTTP::uri] starts_with "/pattern" } {

     

    HTTP::collect

     

    SSL::cert mode require

     

    SSL::renegotiate

     

    set ssl_cert [SSL::cert 0]

     

    set isMatch 0

     

    set org "Company name"

     

    set locality "Warszawa"

     

    set name "www.f5.net"

     

    set country "PL"

     

    set issorg "“Thawte Consulting (Pty) Ltd."

     

    set isscn "Thawte SGC C"

     

    set issctr "Us"

     

    set subject_dn [X509::subject $ssl_cert]

     

    set issuer_dn [X509::issuer $ssl_cert]

     

    log "Client Certificate Received: $subject_dn, $issuer_dn"

     

     

    if { [$subject_dn matches $org] and [$subject_dn matches $locality] and [$subject_dn matches $name] and [$subject_dn matches $country] and [$issuer_dn matches $issorg] and [$issuer_dn matches $isscn] and [$issuer_dn matches $issctr] } {

     

    log "Client Certificate Accepted: $subject_dn, $issuer_dn"

     

    set isMatch 1

     

    pool TestSSL

     

    }

     

    if { $isMatch == 0 }{

     

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

     

    reject

     

    }

     

    }

     

    else {

     

    pool TEST

     

    }

     

    }

     

     

     

    but question is:

     

    I want that script to:

     

     

    1. check for each HTTP connection the URI if it starts with "/pattern"

     

    2. if pattern match require client certificate

     

    3. if client has certificate check the specified record from X.509 cert

     

     

    I have limited possibilities and not much time to test it on F5, thus I would like to prepare the script as good as possible to decrease number of iteration during test phase.

     

     

    and the question is if someone more experienced in scripting could tell if this script has a chances to work as planned.

     

     

  • Jarrod, you joined just to add "owned"? That's helpful...

     

     

    l.majewski, if you want to require a client cert only for specific URIs, you're close. Try checking these related posts for some examples and reply here if you run into any issues.

     

     

    iRule to require SSL Client Certs for a URI (Click here)

     

     

    if no cert rule (Click here)

     

     

    Also, if you have access to the BIG-IP, but can't modify the production virtual servers, you might try adding a test VIP on a separate IP/port or the same IP and different port.

     

     

    Aaron
  • Hi,

     

     

    It is partially working. When the first "if" is true (URI match) then browser is displaying the message with certificates, I choose cert stored on my chip card. Then the PIN window appear, I enter the PIN code to the cert and then on the browser is message cannot display page. In the log generated by script itself there is entry NO cert. I tried even for this code proposed by F5: (I always get the message log:

     

    "No cert found. Holding HTTP request until a client cert is presented..."

     

     

     

     

    when CLIENT_ACCEPTED {

     

    set session_flag 0

     

    }

     

    when CLIENTSSL_HANDSHAKE {

     

    if { [SSL::cert count] != 0 } {

     

    log "Client cert is OK; releasing HTTP request."

     

    HTTP::release

     

    }

     

    }

     

    when HTTP_REQUEST {

     

    if { [HTTP::uri] starts_with "/polcard/" } {

     

    log "Certificate required for: [HTTP::uri]"

     

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

     

    log "No cert found. Holding HTTP request until a client cert is presented..."

     

    HTTP::collect

     

    set session_flag 1

     

    SSL::authenticate always

     

    SSL::authenticate depth 9

     

    SSL::cert mode require

     

    SSL::renegotiate

     

    }

     

    else {

     

    log "crt OK"

     

    pool TestSSL

     

    HTTP::release

     

    }

     

    }

     

    else {

     

    log "No certificate needed for: [HTTP::uri]"

     

    pool Test

     

    }

     

    }

     

     

    It looks like my cert cannot be retrieved from chip card. I use the same card and the same cert to authenticate on another web server and it is working. What is wrong??
  • David_Holmes_9's avatar
    David_Holmes_9
    Historic F5 Account
    L,

     

     

    The code looks good, and indeed, worked just fine for me. I tested using the default software store on Mozilla (which also requires a password).

     

     

    Make sure that your clientssl profile lists the CA in the "client cert ca" attribute.
  • I have code is similar to what mentioned earlier

     

    when CLIENT_ACCEPTED { set session_flag 0 } when CLIENTSSL_HANDSHAKE { if { [SSL::cert count] != 0 } { log "Client cert is OK; releasing HTTP request." HTTP::release } } when HTTP_REQUEST { if { [HTTP::uri] starts_with "/polcard/" } { log "Certificate required for: [HTTP::uri]" if { [SSL::cert count] == 0} { log "No cert found. Holding HTTP request until a client cert is presented..." HTTP::collect set session_flag 1 SSL::authenticate always SSL::authenticate depth 9 SSL::cert mode require SSL::renegotiate } else { log "crt OK" pool TestSSL HTTP::release } } else { log "No certificate needed for: [HTTP::uri]" pool Test } }

     

  • when CLIENT_ACCEPTED { set session_flag 0 } when CLIENTSSL_HANDSHAKE { if { [SSL::cert count] != 0 } { log "Client cert is OK; releasing HTTP request." HTTP::release } } when HTTP_REQUEST { if { [HTTP::uri] starts_with "/polcard/" } { log "Certificate required for: [HTTP::uri]" if { [SSL::cert count] == 0} { log "No cert found. Holding HTTP request until a client cert is presented..." HTTP::collect set session_flag 1 SSL::authenticate always SSL::authenticate depth 9 SSL::cert mode require SSL::renegotiate } else { log "crt OK" pool TestSSL HTTP::release } } else { log "No certificate needed for: [HTTP::uri]" pool Test } }