Forum Discussion

Amit_4274's avatar
Amit_4274
Icon for Nimbostratus rankNimbostratus
Apr 13, 2014

how to compare data-group values

ltm data-group testssl-ma { records { amit { data AMIT2004.abc.com } a { data abcd.abcd.com } b { data AMIT2004.foofoo.com } } type string }

 

when HTTP_REQUEST { set compare_val abcd.abcd.com log local0.error "[class get testssl-ma]" } Output: Apr 13 13:13:03 local/tmm err tmm[3481]: Rule testssl-irule : {amit AMIT2004.abc.com} {a abcd.abcd.com} {b AMIT12004.foofoo.com}

 

How to compare compare_val with testssl-ma data-group VALUES ie AMIT2004.abc.com, etc.

 

7 Replies

  • What is it you're trying to accomplish? I might be misinterpreting things but I'm guessing you want to find a match in the class for compare_val? One thing to know is that the class command typically uses the string and not the value - there might be a way to change that but I've never used it that way. In other words, you should flip the string and the value in your class. So if your class looks like this:

     

    ltm data-group testssl-ma {
        records {
            AMIT2004.abc.com {
                data amit
            }
            abcd.abcd.com {
                data a
            }
            AMIT2004.foofoo.com {
                data b
            }
        }
        type string
    }
    

     

    And your iRule looks like this:

     

    when HTTP_REQUEST {
        set compare_val abcd.abcd.com
        log local0.error "[class match -value $compare_val equals testssl-ma]"
    }
    

     

    You would get a log entry containing an "a", is that what you're trying to do?

  • I am running v11.3 and below is my data-group. I would like to compare my input value ie amit.amit.com with data-group values ie amit.amit.com.au and abcd.abc.com.au and if match is found then do some action otherwise reject

     

        ltm data-group internal /prt-a/testssl-ma {
        records {
            amit.amit.com.au { }
            abcd.abc.com.au { }
        }
        type string
    }
    

     

    Is below irule will provide "abcd.abc.com.au" ??

     

    when HTTP_REQUEST {
        set compare_val abcd.abc.com.au
        log local0.error "[class match -value $compare_val equals testssl-ma]"
    }
    

     

  • No, that will most likely give us an empty string. Consider the anatomy of a data group:

     

    ltm data-group internal /Common/d_group {
        records {
            string_1 {
                data value_1
            }
            string_2 {
                data value_2
            }
        }
        type string
    }
    

     

    In this example string_1 and string_2 are the strings with which we can in different ways match other strings. Furthermore, value_1 and value_2 are the values corresponding to string_1 and string_2 respectively and are an optional part of the data-group record. Normally 'class match' will give you the result 1 if there is a match in the data-group and 0 if there aren't any matches, but the option '-value' will return the value instead of 1 or 0. But since your data-group in your second example doesn't have any values associated with the strings using that option will give us an empty string or possibly cause an error.

    So given your requirement I think you would want an iRule that looks something like this:

     

    when HTTP_REQUEST {
       if { [class match [HTTP::host] equals testssl-ma] }{
          
       }
       else {
          reject
       }
    }
    

     

    So if someone connects to the site using either hostname amit.amit.com.au or abcd.abc.com.au the code of your choice will be executed since the 'class match' will return 1 which equals to 'true' in programming (whereas 0 is false), otherwise the traffic will be rejected.

    Is that what you're looking for?

    Also consider the 'string tolower' command that evaluates the string as if it was all lower-case, because in the above example using hostname amit.amit.com.au would give us a match but AMIT.amit.com.au wouldn't. So using on the HTTP::host would look like this:

     

    [string tolower [HTTP::host]]

     

  • Let me provide more details. Here is my iRule:

     

        when CLIENTSSL_CLIENTCERT {
             Set debug variable to 0 for max performance during normal operations. Only negative events will be log local0.error ged. 
             Set debug variable to 1 for more log local0.error ging i.e. during troubleshooting. Negative and postive events will be log local0.error ged.
            set debug 0
            set client_IP [IP::remote_addr]
            set vs_name [string tolower [virtual name]] 
            set prt_name [string tolower [lindex [split $vs_name /] 1]]
            if {$debug} {log local0.error "Partition name of $vs_name is $prt_name"}
            set dg_name [string tolower [virtual name]-ma]
    
            if {![class exists $dg_name]}{
                log local0.error "Virtual server $vs_name: Data Group $dg_name doesn't exist. Check if the Data Group has been created and whether its name is entirely in lower case."
                reject
                return
                }
             Check if client provided a cert
            if {[SSL::cert 0] eq ""}{  
                 Reset the connection if no client certificate has been presented
                log local0.error "Virtual server $vs_name: Client with IP address $client_IP has not presented client certificate. Connection is rejected."
                reject
                return
            } else {
                 If client cert is presented, check validity and access rights
                if {[SSL::cert count] > 0}{ 
                    set subject_dn [X509::subject [SSL::cert 0]]
                    if {$debug} {log local0.error "Client Certificate Received: $subject_dn"}
                     Check if the certificate is valid
                    if { [SSL::verify_result] == 0 }{
                        Certificate has been verified as valid, now check the CN against the allowed CN list
                         cSSLSubject variable contains only the CN value from the certificate subject
                        set cSSLSubject [string tolower [findstr $subject_dn "CN=" 3 ","]]
                         Reading value inside -ma data-group and changing the case to LOWERCASE
                        set ma_value [string tolower [class get $dg_name]]
                        if {$debug} {log local0.error "SSL Subject CN is: $cSSLSubject"}                
                        Check if the client certificate subject is in the allowed certificate subject access list
                        if {$debug} {log local0.error "$dg_name values: [class get $dg_name]"}                  
                        if { [class match $cSSLSubject contains $ma_value] } {
                             Compare the CN portion of the subject in the presented certificate with the value listed in the access list. 
                             Accept the client cert if its CN is listed in the certificate subject access list.
                             For performance reasons do not turn on log local0.error ging of success events unless troubleshooting
                            if {$debug} {log local0.error "Virtual server $vs_name: Client Certificate with subject $subject_dn has been received from client with an IP address $client_IP.  $cSSLSubject has been found in the Data Group $dg_name, connection has been accepted."}
                        } else {
                            Reject the client cert if it's not in the certificate subject access list
                            log local0.error "Virtual server $vs_name: Client Certificate with subject $subject_dn has been received from client with an IP address $client_IP.  $cSSLSubject has not been found in the Data Group $dg_name, connection would have been rejected."
                            reject
                            return                      
                        }
                    } else {
                         Certificate verification failed. Use the SSL status code in the HTTP response (defined here: http://www.openssl.org/docs/apps/verify.htmlDIAGNOSTICS)
                        set cert_verify_error [X509::verify_cert_error_string [SSL::verify_result]]
                        log local0.error "Virtual server $vs_name: Failed to Verify Client Certificate $subject_dn presented by client with IP $client_IP. SSL verify result: $cert_verify_error. Connection has been rejected."
                        reject
                        return
                    }
                }
                else {
                     Reset the connection if no client certificates
                    log local0.error "Virtual server $vs_name: No client certificate has been presented by client with IP address $client_IP. Connection is rejected."
                    reject
                    return
                }
         }
    }

    data-group name: /olb2-ifweb/sit-iolb-t1-zolb2-ser-c1-v8-443-vsrv-ma

     

    When client tried to access URL with client certificate (sitws1.olb.srv.amit.com.au), it was rejected and below log message was generated.

     

    Apr  8 09:09:25 slot2/AC2004-TILTM2-EPS err tmm1[9319]: Rule /Common/SSLMA-v1.3-allowall : Partition name of /olb2-ifweb/sit-iolb-t1-zol
    b2-ser-c1-v8-443-vsrv is olb2-ifweb
    Apr  8 09:09:25 slot2/AC2004-TILTM2-EPS err tmm1[9319]: Rule /Common/SSLMA-v1.3-allowall : SSL Subject CN is: sitws1.olb.srv.amit.com.au
    Apr  8 09:09:25 slot2/AC2004-TILTM2-EPS err tmm1[9319]: Rule /Common/SSLMA-v1.3-allowall : /olb2-ifweb/sit-iolb-t1-zolb2-ser-c1-v8-443-v
    srv-ma values: {epsir515.unix.srv.amit.com.au {}} {epstammonitoring.test.unix.srv.amit.com.au {}} {sitws1.olb.srv.amit.com.au {}}
    Apr  8 09:09:25 slot2/AC2004-TILTM2-EPS err tmm1[9319]: 01220001:3: TCL error: /Common/SSLMA-v1.3-allowall  - can't read "ma": no such v
    ariable     while executing "class match $cSSLSubject equals $ma-value"

    However, data-group is configured with sitws1.olb.srv.amit.com.au in below format:

     

    ltm data-group internal /olb2-ifweb/sit-iolb-t1-zolb2-ser-c1-v8-443-vsrv-ma {
        records {
            epsir515.unix.srv.amit.com.au {}
            epstammonitoring.test.unix.srv.amit.com.au {}
            sitws1.olb.srv.amit.com.au {}
        }
        type string
    }
  • since sitws1.olb.srv.amit.com.au is not in data (value) part, can't you just use normal class match command?

     

  • e.g.

     

     config
    
    [root@ve11a:Active:In Sync] config  tmsh list ltm data-group internal sit-iolb-t1-zolb2-ser-c1-v8-443-vsrv-ma
    ltm data-group internal sit-iolb-t1-zolb2-ser-c1-v8-443-vsrv-ma {
        records {
            epsir515.unix.srv.amit.com.au { }
            epstammonitoring.test.unix.srv.amit.com.au { }
            sitws1.olb.srv.amit.com.au { }
        }
        type string
    }
    [root@ve11a:Active:In Sync] config  tmsh list ltm rule qux
    ltm rule qux {
        when RULE_INIT {
      if { !([TMM::cmp_group] == 0 and [TMM::cmp_unit] == 0) } { return }
      set sbj "sitws1.olb.srv.amit.com.au"
      if { [class match -- $sbj eq sit-iolb-t1-zolb2-ser-c1-v8-443-vsrv-ma] } {
        log local0. "match"
      } else {
        log local0. "not match"
      }
    }
    }
    
     /var/log/ltm
    
    [root@ve11a:Active:In Sync] config  tail -f /var/log/ltm
    Apr 21 21:48:19 ve11a info tmm[13593]: Rule /Common/qux : match
    

     

  • The log message seems to be from an earlier incarnation of the iRule since the message seems to complain about the fact that there is a dash in the variable name which is interpreted as a minus sign, thus the TCL error. But in the code the dash is replaced with an underscore so you shouldn't get the same error message with that code.

     

    Furthermore, the class match is used with a class name but in this case you're using a variable containing a list of the elements in the class which isn't the same thing. Maybe you should try using the variable containing the class name instead in the class match statement:

     

    [class match $cSSLSubject contains $dg_name]

     

    I have never tried myself to use a variable instead of the actual object name so I don't know if that's an issue but I've seen people use the same concept for selecting pools so it might be okay.