Forum Discussion

mikegray_198028's avatar
Jan 20, 2017

irule help

Hello Team,

I am looking for irule for the below scenario.

  1. https://www.example.com/user1
    > for this user will submit client certificate with cn=user1 LB should accept this connection and reject all other connections.
  2. https://www.example.com/user2
    > for this user will submit client certificate with cn=user2 LB should accept this connection and reject all other connections.
  • JG's avatar
    JG
    Icon for Cumulonimbus rankCumulonimbus

    Here's one in its simplest form:

    when CLIENTSSL_CLIENTCERT {
        set subject_dn 0
         Check if client provided a cert
        if { [SSL::cert count] > 0 } {
            set subject_dn [X509::subject [SSL::cert 0]]
        }
    }
    
    when HTTP_REQUEST {
        set user_in_path [string trim [HTTP::uri] "/"]
        if { ! ($subject_dn contains "cn=$user_in_path") } {
            reject
        }
    }
    
  • JG's avatar
    JG
    Icon for Cumulonimbus rankCumulonimbus

    Would this one work for you:

    when CLIENT_ACCEPTED {
        array set CNs {}
    }
    
    when CLIENTSSL_CLIENTCERT {
        for {set i 0} {$i < [SSL::cert count]} {incr i}{
            log local0. "[IP::client_addr]:[TCP::client_port]: cert $i; subject=[X509::subject [SSL::cert $i]];\
            [X509::issuer [SSL::cert $i]]; cert_serial=[X509::serial_number [SSL::cert $i]];"
            set CNs([X509::subject [SSL::cert $i]]) 1
        }
    }
    
    when HTTP_REQUEST {
        switch -glob [HTTP::uri] {
            "/abcdef" {
                         if { ! ([info exists CNs("cn=frontofficeuser")]) } {
                             log local0. "[IP::client_addr]:[TCP::client_port]: [HTTP::uri] : rejected."
                             reject
                         }
            }
            "/bcdefg" {
                         if { ! ([info exists CNs("cn=hruser")]) } {
                             log local0. "[IP::client_addr]:[TCP::client_port]: [HTTP::uri] : rejected."
                             reject
                         }
            }
            "/cdefgh" {
                         if { ! ([info exists CNs("cn=facilitiesuser")]) } {
                             log local0. "[IP::client_addr]:[TCP::client_port]: [HTTP::uri] : rejected."
                             reject
                         }
            }
            default {
                        reject
                        log local0. "[IP::client_addr]:[TCP::client_port]: [HTTP::uri] : rejected."
            }
        }
    }
    

    ?

  • Only the leaf cert, [SSL::cert 0] is used for client SSL checking. This should also work;-

    when HTTP_REQUEST {
        set cn [class match -value [HTTP::path] starts_with dg_path_common_name_mapping]
    
        if {$cn ne ""} {
            Client certificate is required for this path  
           if {![SSL::cert count]} {
              HTTP::respond 403 content "Client certificate required" noserver
              return
           } elseif {!([X509::subject [SSL::cert 0]] contains $cn)} {
               Client cert doesn't match required Common Name
              HTTP::respond 403 content "Client certificate does not match required name $cn" noserver
              return
           }
        }
    }
    
  • Hi,

    you can use this irule:

    when CLIENTSSL_HANDSHAKE {
      if {![info exists username]} {set username ""}
    }
    
    when CLIENTSSL_CLIENTCERT {
         Check if client provided a cert
        if { [SSL::cert count] > 0 } {
            set username [regsub -all ".*CN=(.\[^,\]*),.*$" [X509::subject [SSL::cert 0]] {\1}]
        }
    }
    
    when HTTP_REQUEST {
        if {[HTTP::uri] equals /} {
            HTTP::redirect "/$username"
        }elseif { !([HTTP::uri] starts_with "/$username") } {
            HTTP::respond 403 content {
                
                Not authorized
                You are not autorized to access this website
                
            } noserver
        }
    }