Forum Discussion

Steven_87308's avatar
Steven_87308
Icon for Nimbostratus rankNimbostratus
Feb 10, 2012

stuck on first complex irule - req for help

I'm writing to ask for help with the design of an irule solution. My goal is to get various URIs to either redirect to SSL during authentication, or to fail pass http through to a standard pool.

 

Example:

 

>

 

>

 

> pool1

 

> pool1

 

 

I have tried data groups, but Big-IP v11.1, on clicking "create," gives an error that says "requested string class member (/Common/redirectPathDataGroup Path) already exists in partition common.

 

This confuses me, for it is the first data group I created. Well, the second, I tried again with a different datagroup and variable name. Maybe its the variable name that confuses me...

 

redirectPathDataGroup

 

/path1

 

/path2

 

 

Yet in the gui it wants

 

Name (=redirectPathDataGroup)

 

Type (=string)

 

Records (string,value), (path,/path1), (path,/path2)

 

 

That errored out as described above. It would not let me reference it, for it said the string was missing. (How can it be missing if above it says it already exists? Is it because I used nvar path twice, that is, in two records?)

 

 

 

I have tried using logical operators...

 

when HTTP_REQUEST {

 

if { ([HTTP::uri] ends_with "/path1") or ([HTTP::uri] starts_with "/path2") } {

 

HTTP::redirect https://[HTTP::host][HTTP::uri]

 

} else

 

pool /Common/FusV-F5-T1_http_pool

 

}

 

}

 

... but that goes right to http, as if it is skipping the IF test.

 

 

Similarly, I have tried simplifying things, creating 3 irules, ordering them IF path1, redir, 2) IF path2, redir, 3) default pool --- same thing. Despite the last rule being, well, last, it runs as though it is first.

 

 

I have tried nesting; if path1, redir, if path2, redir, else pool--no go. Or if path1, if path2, redir, else pool -- no go.

 

 

I'm at a loss. Suggestions?

 

 

  • Are data-groups a requirement? It seems like you could use something like this:

    
    when HTTP_REQUEST {
      set PATH [HTTP::path]
      switch $PATH {
        "/path1"  { HTTP::redirect "https://hostname/path1" }
        "/path2"  { HTTP::redirect "https://hostname/path2" }
        "/path3"  { pool pool1 }
        default  { pool2 }
      }
    } 
     

    Unless the situation is more complex, I would think that would work.

    Of note, in v10 I ran into a bug where you couldn't enter a record in a data-group with a leading slash (/). The workaround was to use the bigpipe shell which I don't believe is an option in v11. Just saying as there might be a bug causing your frustration. Maybe someone will be able to comment on that.

    Hope that helps.

    Richard
  • this is based on richard's suggestion.

    root@ve1110(Active)(/Common)(tmos) list ltm virtual bar
    ltm virtual bar {
        destination 172.28.19.252:80
        ip-protocol tcp
        mask 255.255.255.255
        profiles {
            http { }
            tcp { }
        }
        rules {
            myrule
        }
        snat automap
        vlans-disabled
    }
    root@ve1110(Active)(/Common)(tmos) list ltm rule myrule
    ltm rule myrule {
        when HTTP_REQUEST {
       set uri [HTTP::uri]
       switch -glob [string tolower $uri] {
          "/path1*"  -
          "/path2*"  { HTTP::redirect "https://[HTTP::host][HTTP::uri]" }
          "/path3*"  -
          "/path4*" { pool pool1 }
          default  { pool pool2 }
       }
    }
    
    when HTTP_RESPONSE {
       log local0. "[IP::client_addr]:[TCP::client_port] | $uri | [IP::remote_addr]:[TCP::remote_port]"
    }
    }
    root@ve1110(Active)(/Common)(tmos) list ltm pool pool1
    ltm pool pool1 {
        members {
            200.200.200.101:80 {
                address 200.200.200.101
            }
        }
    }
    root@ve1110(Active)(/Common)(tmos) list ltm pool pool2
    ltm pool pool2 {
        members {
            200.200.200.102:80 {
                address 200.200.200.102
            }
        }
    }
    
    [root@ve1110:Active] config  curl -I http://172.28.19.252/path1/whatever?a=1
    HTTP/1.0 302 Found
    Location: https://172.28.19.252/path1/whatever?a=1
    Server: BigIP
    Connection: Keep-Alive
    Content-Length: 0
    
    [root@ve1110:Active] config  curl -I http://172.28.19.252/path2/whatever?a=1
    HTTP/1.0 302 Found
    Location: https://172.28.19.252/path2/whatever?a=1
    Server: BigIP
    Connection: Keep-Alive
    Content-Length: 0
    
    [root@ve1110:Active] config  curl -I http://172.28.19.252/path3/whatever?a=1
    HTTP/1.1 404 Not Found
    Date: Sat, 11 Feb 2012 02:50:43 GMT
    Server: Apache/2.2.3 (CentOS)
    Content-Type: text/html; charset=iso-8859-1
    
    [root@ve1110:Active] config  curl -I http://172.28.19.252/path4/whatever?a=1
    HTTP/1.1 404 Not Found
    Date: Sat, 11 Feb 2012 02:50:53 GMT
    Server: Apache/2.2.3 (CentOS)
    Content-Type: text/html; charset=iso-8859-1
    
    [root@ve1110:Active] config  curl -I http://172.28.19.252/whatever?a=1
    HTTP/1.1 404 Not Found
    Date: Sat, 11 Feb 2012 02:46:23 GMT
    Server: Apache/2.2.3 (CentOS)
    Content-Type: text/html; charset=iso-8859-1
    
    [root@ve1110:Active] config  cat /var/log/ltm
    Feb 10 18:42:08 tmm info tmm[7321]: Rule /Common/myrule : 172.28.19.253:46156 | /path3/whatever?a=1 | 200.200.200.101:80
    Feb 10 18:42:18 tmm info tmm[7321]: Rule /Common/myrule : 172.28.19.253:46160 | /path4/whatever?a=1 | 200.200.200.101:80
    Feb 10 18:42:23 tmm info tmm[7321]: Rule /Common/myrule : 172.28.19.253:46162 | /whatever?a=1 | 200.200.200.102:80
    
  • for data group, i understand string value must be unique.

    this is an example.

    root@ve1110(Active)(/Common)(tmos) list ltm data-group internal redirectPathDataGroup
    ltm data-group internal redirectPathDataGroup {
        records {
            /path1 { }
            /path2 { }
        }
        type string
    }
    root@ve1110(Active)(/Common)(tmos) list ltm data-group internal poolPathDataGroup
    ltm data-group internal poolPathDataGroup {
        records {
            /path3 {
                data pool1
            }
            /path4 {
                data pool1
            }
        }
        type string
    }
    root@ve1110(Active)(/Common)(tmos) list ltm rule myrule
    ltm rule myrule {
        when HTTP_REQUEST {
       set uri [HTTP::uri]
    
       if {[class match -- [string tolower $uri] starts_with redirectPathDataGroup]} {
          HTTP::redirect "https://[HTTP::host][HTTP::uri]"
       } elseif {[class match -- [string tolower $uri] starts_with poolPathDataGroup]} {
          pool [class match -value [string tolower $uri] starts_with poolPathDataGroup]
       } else {
          pool pool2
       }
    }
    
    when HTTP_RESPONSE {
       log local0. "[IP::client_addr]:[TCP::client_port] | $uri | [IP::remote_addr]:[TCP::remote_port]"
    }
    }
    
    [root@ve1110:Active] config  curl -I http://172.28.19.252/path1/whatever?a=1
    HTTP/1.0 302 Found
    Location: https://172.28.19.252/path1/whatever?a=1
    Server: BigIP
    Connection: Keep-Alive
    Content-Length: 0
    
    [root@ve1110:Active] config  curl -I http://172.28.19.252/path2/whatever?a=1
    HTTP/1.0 302 Found
    Location: https://172.28.19.252/path2/whatever?a=1
    Server: BigIP
    Connection: Keep-Alive
    Content-Length: 0
    
    [root@ve1110:Active] config  curl -I http://172.28.19.252/path3/whatever?a=1
    HTTP/1.1 404 Not Found
    Date: Sat, 11 Feb 2012 02:58:59 GMT
    Server: Apache/2.2.3 (CentOS)
    Content-Type: text/html; charset=iso-8859-1
    
    [root@ve1110:Active] config  curl -I http://172.28.19.252/path4/whatever?a=1
    HTTP/1.1 404 Not Found
    Date: Sat, 11 Feb 2012 02:59:02 GMT
    Server: Apache/2.2.3 (CentOS)
    Content-Type: text/html; charset=iso-8859-1
    
    [root@ve1110:Active] config  curl -I http://172.28.19.252/whatever?a=1
    HTTP/1.1 404 Not Found
    Date: Sat, 11 Feb 2012 02:54:30 GMT
    Server: Apache/2.2.3 (CentOS)
    Content-Type: text/html; charset=iso-8859-1
    
    [root@ve1110:Active] config  cat /var/log/ltm
    Feb 10 18:50:24 tmm info tmm[7321]: Rule /Common/myrule : 172.28.19.253:34440 | /path3/whatever?a=1 | 200.200.200.101:80
    Feb 10 18:50:26 tmm info tmm[7321]: Rule /Common/myrule : 172.28.19.253:34442 | /path4/whatever?a=1 | 200.200.200.101:80
    Feb 10 18:50:30 tmm info tmm[7321]: Rule /Common/myrule : 172.28.19.253:34443 | /whatever?a=1 | 200.200.200.102:80
    
  • Richard, thanks for the reply.

     

     

     

    I'm not sure I understand the use of -glob -- wouldn't it be similar to an OR statement in the first IF test? I tried modifying your snippet, but am confused, for it seems to use PATH as a variable, to be found in -glob. If I declare the paths in -glob, I'd still want a redirect, not a path if there is a match. Point is, it doesn't work -- it doesn't redirect, nor on the same path.

     

    IF-OR-Else

     

    when HTTP_REQUEST {

     

    if {{[HTTP::uri] starts_with "/path1"} or {[HTTP::uri] ends_with "/path2"}} {

     

    HTTP::redirect https://[HTTP::host][HTTP::uri]

     

    } else {

     

    pool http_poolX

     

    }

     

     

    so I tried to do a nest again. Here's what I have, and in terms of parsing, Big-IP likes it and lets me save...

     

     

     

    If-elseif

     

    when HTTP_REQUEST {

     

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

     

    HTTP::redirect https://[HTTP::host][HTTP::uri]

     

    } elseif {[HTTP::uri] ends_with "/path2"} {

     

    HTTP::redirect https://[HTTP::host][HTTP::uri]

     

    } else {

     

    pool http_poolX

     

    }

     

    }

     

     

    These gets me no redirects - it seems to not match, giong straight to a basic (non-ssl) authentication dialog, or sometimes it will say, "Unable to open . Cannot download the information you requested."

     

     

    Nitass, is your post a proof of concept, if I read correctly? Why wouldn't the above work when -glob does?

     

    Curious,

     

    -Steve

     

     

     

     

  • You have an extra set of curly braces in yours. This should work:

     

     

    if {[HTTP::uri] starts_with "/path1" or [HTTP::uri] ends_with "/path2"} {

     

     

    But a switch statement or class command and data group should be more efficient and manageable.

     

     

    Aaron