Forum Discussion

Andreia's avatar
Andreia
Icon for Cirrus rankCirrus
Feb 14, 2023

[HELP PLEASE!] Client Certificate Validation based on URI

Hello!

I need help making an iRule that does the following:

1 - if the request goes to "/auth" the client's certificate is not validated, but when BIG-IP forwards a request to the API server in the pool, that API server will validate the serverssl profile (mTLS) certificate.
2 - any other request "/", the client's certificate will be validated and if it is not in the "trusted certificate authorities", the request will be answered with 403. If the certificate is validated, the request will be forwarded to the API server, which will validate the serverssl profile certificate.

I found out another iRule similar to the one I need but when I do the request to URI /auth, there's no browser pop-up to select the cliente certificate.

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 "/auth" } {
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 "No certificate needed for: [HTTP::uri]"
}
}

 

 

Can someone help, please?

Thanks

7 Replies

  • 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 "/auth" } {
    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 "No certificate needed for: [HTTP::uri]"
    }
    }

     

    When I make a request for the /auth URI there is no browser pop-up to select the client certificate.

  • Andreia You might try the following iRule but I'm not 100% positive if this is the correct iRule so please do some testing prior to implementing this in production to ensure it is working the way you would expect.

     

    when CLIENT_ACCEPTED priority 500 {
    
        set session_flag 0
    
    }
    
    when CLIENTSSL_HANDSHAKE priority 500 {
    
        if { [SSL::cert count] != 0 } {
            log "Client cert is OK; releasing HTTP request."
            HTTP::release
        }
    
    }
    
    when HTTP_REQUEST priority 500 {
    
        set URI [string tolower [HTTP::uri]]
    
        if { !(${URI} starts_with "/auth") } {
            log "Certificate required for: ${URI}"
    
            HTTP::collect
            set session_flag 1
            SSL::authenticate always
            SSL::authenticate depth 9
            SSL::cert mode require
            SSL::renegotiate
    
            if { [SSL::cert count] > 0} {
                if { [SSL::verify_result] == 0 }{
                    return
                } else {
                    set error_string [X509::verify_cert_error_string [SSL::verify_result]]
                }
                
            } else {
                set error_string "No client certificate provided"
                HTTP::respond 403 content "<html>Invalid client certificate: ${error_string}</html>"
            }
        } else {
            log "No certificate needed for: ${URI}"
        }
    
    }

     

    • Andreia's avatar
      Andreia
      Icon for Cirrus rankCirrus

      Hi,  Paulius !

      Thank you for replying! I pasted the iRule in the test environment and the behavior is the same:
      no pop-up window on the browser to select the client certificate. (there's a way to make this pop-up does not appear as happens on nginx with the "ssl_verify_client on" line? OK! I'm sorry I'm overlapping subjects! I will not go on with it right now.)

      What is leaving me in doubt is because when I do a simple irule, with these same settings in the Profile SSL Client, with the list of certificates selected in the "Trusted Certificate Authorities", it works! But I actually need to handle this URI-related conditional. And if we try to do the opposite: when the request goes to "/auth" it wil turn OFF this client certificate verification? Can you help me with this?

      Thanks!

    • Andreia's avatar
      Andreia
      Icon for Cirrus rankCirrus

      Paulius,

      I did the test again on "In Private" mode. Look what logs reported:

      Feb 15 10:48:28  err tmm1[16269]: 01220001:3: TCL error: /Common/irule_auth-opin-dev_v2 <HTTP_REQUEST> - can't read "error_strign": no such variable while executing "HTTP::respond 403 content "<html>Invalid client certificate: ${error_strign}</html>""
      Feb 15 10:48:28 info tmm6[16269]: 01220002:6: Rule /Common/irule_auth-opin-dev_v2 <HTTP_REQUEST>: Certificate required for: /xyz/abc/customers/management/health
      Feb 15 10:48:28  err tmm6[16269]: 01220001:3: TCL error: /Common/irule_auth-opin-dev_v2 <HTTP_REQUEST> - can't read "error_strign": no such variable while executing "HTTP::respond 403 content "<html>Invalid client certificate: ${error_strign}</html>""

      Can you help?

      Thank you!

      • Andreia's avatar
        Andreia
        Icon for Cirrus rankCirrus

        Paulius,

        I fixed the ${error_strign} to ${error_string} and now I'm receving connection reset when I do a request to another URI that is not /auth. For /auth URI goes Ok!

        I'm sorry for a lot of answers it's because I'm reporting while I'm doing the tests.