For more information regarding the security incident at F5, the actions we are taking to address it, and our ongoing efforts to protect our customers, click here.

Forum Discussion

Guilherme's avatar
Guilherme
Icon for Nimbostratus rankNimbostratus
Feb 18, 2020

Help with irule structure

Hi sirs,

I just wrote a rule that reads a specific HTTP header and saves it to USER_COD and if it has an empty value or PRINT value it should forward the connection to a certain pool, if the this value is a specific number (can be like 1-999), this number should be compared against numbers that are inside the datagroups and if there is a match the connection will be forwarded to the correct pool, if no value is available in the datagroups to compare against, the default pool will be chosen. Unfortunately I am not a great expert in programming (as you guys can see) and during the tests I got several errors in variables reading, I believe that error is related to the irule structure when try to save the value (when receiving PRINT or empty) and when the value is compared to the datagroup, I really need a help with the experts guys that live here hehe

when RULE_INIT {
# 0 - log off
# 1 - log on
set static::debug_user_cod 0
}
when HTTP_REQUEST {
#	checks if the USER_COD is empty or PRINT
if {[HTTP::header value "USER_COD"] equals "" or "PRINT" }  {
# 	save it on USER_COD_NULL
	set USER_COD_NULL [HTTP::header value "USER_COD"]
#	forward to pool_default
	pool POOL_DEFAULT
#	show log
	if { $static::debug_user_cod } { log local0. "src: [IP::client_addr] get USER_COD: $USER_COD - send it to default pool" }
#	If USER_COD contains numbers save it on USER_COD to compare with DGs
} else { set USER_COD [HTTP::header value "USER_COD"] }
#	show log	
if { $static::debug_user_cod } {
	set HTTP_DEBUG_COD "src: [IP::client_addr] URL -> [HTTP::host][HTTP::uri]"
	log local0. "----------------------------------------"
	log local0. "$HTTP_DEBUG_COD (REQUEST)"
	log local0. "Value get on USER_COD: $USER_COD"
	log local0. "----------------------------------------"
	}
#	Compare the number saved on USER_COD with DGs to forward for the specific pool
if { $USER_COD == $DG_01 } {
	pool POOL_DG_01
} elseif { $USER_COD == $DG_02 } {
	pool POOL_DG_02
} elseif { $USER_COD == $DG_03 } {
	pool POOL_DG_03
} elseif { $USER_COD == $DG_04 } {
	pool POOL_DG_04
} elseif { $USER_COD == $DG_05 } {
	pool POOL_DG_05
} elseif { $USER_COD == $DG_06 } {
	pool POOL_DG_06
} elseif { $USER_COD == $DG_07 } {
	pool POOL_DG_07
#	If no values match forward it to default one
} else { pool POOL_DEFAULT }
}
when SERVER_CONNECTED {
    if { $static::debug_user_cod } { 
	log local0. "----------------------------------------"
	log local0. "src: [IP::local_addr] - Dst Member: [IP::remote_addr] - USER_COD: $USER_COD"
	log local0. "----------------------------------------"
}
}

Erros that I got during the tests (a lot of them):

 TCL error: /Common/test_log <HTTP_REQUEST> - invalid command name "894"    while executing "$USER_COD"

test_log <HTTP_REQUEST> - can't read "USER_COD": no such variable   while executing "if {[HTTP::header value "USER_COD"] equals "" or "PRINT" }"") }

Looking for a help from you guys... and thanks for everyone who is available to read my post.

5 Replies

  • Hi

    Try something like this...

    when RULE_INIT {
    # 0 - log off
    # 1 - log on
    set static::debug_user_cod 0
    }
     
    when HTTP_REQUEST {
     
        if { $static::debug_user_cod } {
         set USER_COD [HTTP::header value "USER_COD"]
        }
    	
    	#Switch through the values of header USER_COD. If a value matches then send to appropiate pool
    	#if no value matches,including value PRINT or a null value then send to default pool
    	
    	
    	switch -glob [string tolower [HTTP::header value "USER_COD"]] {
    		"dg_01"		{pool POOL_DG_01}
    		"dg_02"		{pool POOL_DG_02}
    		"dg_03"		{pool POOL_DG_03}
    		"dg_04"		{pool POOL_DG_04}
    		"dg_05"		{pool POOL_DG_05}
    		"dg_06"		{pool POOL_DG_06}
    		"dg_07"		{pool POOL_DG_07}
    		default 	{pool POOL_DEFAULT
    		            if { $static::debug_user_cod } {
    		            	log local0. "----------------------------------------"
    	                    log local0. "src: [IP::client_addr] URL -> [HTTP::host][HTTP::uri] (REQUEST)"
    	                    log local0. "Value get on USER_COD: $USER_COD"
    	                    log local0. "----------------------------------------"
    		                } 
    		            }
            }
    }
     
    when SERVER_CONNECTED {
        if { $static::debug_user_cod } { 
    	log local0. "----------------------------------------"
    	log local0. "src: [IP::local_addr] - Dst Member: [IP::remote_addr] - USER_COD: $USER_COD"
    	log local0. "----------------------------------------"
    }
    }
    • Guilherme's avatar
      Guilherme
      Icon for Nimbostratus rankNimbostratus

      Hi iaine,

      Thank you! I cant test right now but I still with a doubt.. how can I insert the empty value into to the datagroup ? There is some situations that header comes empty or with PRINT value and It must be send to a specific pool, may I use the default condition ?

  • Hi

     

    If the header value is null then this should get picked up by the default logic at the end of the code and sent to the default_pool.

     

    The code is written so that is there is a match on a dg_## value in the header then the request will get sent to the corresponding pool. All other requests (ie non-matching) will get sent to the default_pool

    • Guilherme's avatar
      Guilherme
      Icon for Nimbostratus rankNimbostratus

      OK I got you! Im wondering how the switch will call values in the datagroup, it doesnt need to use the "class" match command ?

  • hi

     

    so if you wanted to use a data group, then the code would look something like...

       when HTTP_REQUEST {
          set app_pool [class match -value -- [HTTP::header value "USER_COD"] eq cod_value]
          if {$app_pool ne ""} {
             pool $app_pool
          } else {
             pool default_pool
          }
       }

    ...where cod_value is the name of the data group

     

    ltm data-group internal /Common/cod_value {

      records {

        DG_01 {

          data Pool_01

        }

      }

      type string

    }