Forum Discussion

Grandiser's avatar
Grandiser
Icon for Nimbostratus rankNimbostratus
Jan 31, 2024
Solved

Can I have a data group, with "data group" members

Hi;

I am trying to have an i-rule that checks for URLs in a data group, then based on the URL value it allows certain methods. 

 

For example, the URL path /abc/xyz/ can have GET and POST. However a different URL path can only have GET.

 

It would be great if I can check the URL against a certain data group of URLs and then for each URL in this data group, there is a specific data group of http methods.

 

I guess more like a two dimensional array or like a data group of URLs but each member is a "URL and its associated methods". 

 

Or a data group with "data group" members, each member is referenced by a URL and has a list of methods.

 

Kindly

Wasfi

  • I did a quick test and this seems to work pretty well. You'll want to use an "allow list" rather than a "block list" for security reasons.

    Of course all code should be thoroughly tested before use in production. Use at your own risk.

     

    when HTTP_REQUEST {
      set uri_path_name [string tolower [HTTP::uri] ]
      set http_method [string toupper [HTTP::method] ]
      set allowed_methods [class match -value $uri_path_name equals http_method_allowlist ]
      log local0. "Allowed methods: $allowed_methods for URI: ${uri_path_name}, this request is ${http_method}"
      if { [expr { ${allowed_methods} contains ${http_method} } ] } {
        log local0. "allow"
        return
      } else {
        log local0. "disallow"
        reject
        return
      }   
    }

     

4 Replies

  • Sounds like a great project. I'd go for the spirit of maintainability and avoid two-dimensional stuff in favor of using some kind of simple delimiter in the data section like this:

    ltm data group internal http_method_acls {
        records {
            /foo/bar {
                data "POST|CONNECT|GET|HEAD"
            }
        type string
    }

     

    Then to check for a match you can just use "contains [HTTP::method]", which has extra fast optimization (as compared to the stock TCL string functions) in the iRules engine. Maybe something kind of like this:

    when HTTP_REQUEST {
        set allowedmethods [class match -value [string tolower [HTTP::path]] eq http_method_acls ]
        if { allowedmethods contains [HTTP::method] } { 
            log local0. "allowed"
        } else {
            log local0. "deny"
            HTTP::respond 400 "not allowed here"
        } 
    }

    We do sell a module called "Advanced WAF" that can do this kind of filtering automatically if you have these allowed definitions created already in an OpenAPI spec file: https://my.f5.com/manage/s/article/K81943444

     

     

    • Grandiser's avatar
      Grandiser
      Icon for Nimbostratus rankNimbostratus

      Hi Lucas;

       

      Thank you for your response. Just wanted to check the syntax for your suggestion though. For example, would this work? The idea is to allow the request if the URL and HTTP method match. If only the URL is a match then deny. and if the URL is not a match then allow everything.

      ltm data group internal http_method_acls {
          records {
              /foo/bar/ {
                  data "POST|CONNECT|GET|HEAD"
              }
              /abc/xyz/ {
                  data "POST"
              }
          }
          type string
      }
      when HTTP_REQUEST {
          set uri_path_name [string tolower [URI::path [HTTP::uri]]]
          set http_method [string toupper [HTTP::method]]
          if {! [class match $uri_path_name equals http_method_acl] } {
              return
          } else {
              if {![class match $uri_path_name -value contains $http_method]} {
                  reject
                  return
              }   
          }
      }

       

       

      • Lucas_Thompson's avatar
        Lucas_Thompson
        Icon for Employee rankEmployee

        I did a quick test and this seems to work pretty well. You'll want to use an "allow list" rather than a "block list" for security reasons.

        Of course all code should be thoroughly tested before use in production. Use at your own risk.

         

        when HTTP_REQUEST {
          set uri_path_name [string tolower [HTTP::uri] ]
          set http_method [string toupper [HTTP::method] ]
          set allowed_methods [class match -value $uri_path_name equals http_method_allowlist ]
          log local0. "Allowed methods: $allowed_methods for URI: ${uri_path_name}, this request is ${http_method}"
          if { [expr { ${allowed_methods} contains ${http_method} } ] } {
            log local0. "allow"
            return
          } else {
            log local0. "disallow"
            reject
            return
          }   
        }