Forum Discussion

7 Replies

  • Colin_Walker_12's avatar
    Colin_Walker_12
    Historic F5 Account
    I know there have been several people who have used iRules to offload authentication, even HTTP auth, but iRules won't be able to read any information stored on the Webserver's filesystem. If you wanted to store the valid usernames/passwords on the BIG-IP, or in some authentication resource like an LDAP server, there are profiles to allow for the offloading of auth that way.

     

     

    Colin
  • I am in a situation where we have websites that are not sensitive but policy requires a password to be placed on them. I was wondering if you could point me in the right direction to writing an iRule that could prompt for a username and password and compare them to something like the string "test" Not secure, but easy.

     

     

    Having looked through many of the other authentication systems I haven't been able to use any of them since I don't have a license for that component, and I would like to do without the complexity. Any help would be greatly appreciated!
  • You can check the wikipedia page (Click here) for details on basic HTTP auth. You could use a rule to check for the authorization header, split the header value, base64 decode the user:pass and verify it's in an allowed list. If not, send back a 401 response.

    If it's just one user:pass that you need to support, you could base64 encode the value and check for that rather than base64 decoding every value in the request. If you have multiple logins, you could add them to a datagroup.

    Example request with an authorization header:

    GET /private/index.html HTTP/1.0

    Host: localhost

    Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

    Here is an untested example:

      
      when RULE_INIT {  
        
          Set the single username and password here delimited with a colon  
         set ::global_user_pass "testuser:testpass"  
        
          Base64 encode the user:pass  
         set ::global_user_pass [b64encode $::global_user_pass]  
        
         log local0. "Encoded \$::global_user_pass: $::global_user_pass "  
      }  
      when HTTP_REQUEST {  
        
         log local0. "[IP::client_addr]:[TCP::client_port]: New HTTP request to \ 
           [HTTP::host][HTTP::uri] with auth value: [HTTP::header value Authorization]"  
        
          Check if there is an authorization header with a length  
         if {[string length [HTTP::header value "Authorization"]]}{  
        
             Get the second field from the header value  
            set encoded_user_pass [getfield [HTTP::header value "Authorization"] " " 2]  
            log local0. "[IP::client_addr]:[TCP::client_port]: Parsed Authorization value $encoded_user_pass"  
        
             Check the encoded user:pass from the request against the global user:pass  
            if {$encoded_user_pass eq $::global_user_pass}{  
        
                Credentials were okay, so exit this rule (don't send a 401 response  
               log local0. "[IP::client_addr]:[TCP::client_port]: credentials were valid."  
       return  
            } 
         } 
          If we got here, the request didn't contain a valid user:pass, so send a 401 response to prompt user for credentials.  
          The format for HTTP::respond is the content and then space delimited header name followed by the header value  
         HTTP::respond 401 content {        "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">  
                  
                    
                    Error  
                      
                    
                  401 Unauthorised.  
                } WWW-Authenticate "Basic realm=\"Secure Area\""  
        
         log local0. "[IP::client_addr]:[TCP::client_port]: Sending 401 response."  
      }  
      

    Once you're done testing, you could remove the intermediate variable, $encoded_user_pass and disable the logging.

    Aaron
  • Aaron,

     

     

    Thank you very much for your for your solution and your prompt reply. Everything works perfectly.

     

     

    Thanks,

     

    ~ Mike
  • Hello there,

    I want to make this iRule more dynamic. So I insert a new META-Tag:

    HTTP::respond 401 content { "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd"> 
      
      
     Redirect 
      
      
     401 Unauthorised. 
     } WWW-Authenticate "Basic realm=\"Secure Area\""

    But now I want to change the "URL" with "[HTTP::host]". I try to do this since hours but it doesn't work.

    Perhaps someone has an idea.

    bikmaek
  • If you use curly braces { } to include the HTML, you don't have to escape the single quotes within the HTML. But the curly braces also prevent expansion of variables. If you replace the curly braces with double quotes, then you can include commands like HTTP::host. But you have to escape the double quotes in the HTML:

     

     

    HTTP::respond 401 content " ... "

     

     

    Aaron