Forum Discussion
mahnsc
Apr 06, 2012Nimbostratus
Multi-Conditional iRule using Basic Auth and 9.4.3
I received a request recently regarding a customer of my customer who
has multiple authentication and authorization requirements for web
service requests. The requirements were broken down as follows:
1. Requests only matching URI named "/uri/" should be validated.
2. Requests with a Content-Type of "text/xml" should be validated.
3. Requests must only be allowed from IP address w.x.y.z
4. Requests must be protected with basic auth userid/password
My OS version is 9.4.3
I have written the following rule, which intends to follow these
guidelines but I have doubts that line 7 will do what I'm hoping it will
do. Building off of the rule from the HTTP Basic Access Authentication
iRule Style article, this is what I currently have:
when HTTP_REQUEST {
if {[HTTP::uri] contains "/uri/"} {
if { [HTTP::header "Content-Type"] contains "text/xml" } {
if { ! ( [IP::addr [IP::client_addr] equals w.x.y.z/m.a.s.k] ) } {
if { [HTTP::header exists Authorization] } {
binary scan [md5 [HTTP::password]] H* password
if { [matchclass [HTTP::username] equals $users] equals $password } {
log local0. "User [HTTP::username] authorized to access /uri/"
} elseif { [string length [HTTP::password]] != 0} {
log local0. "User [HTTP::username] not authorized to access /uri/"
HTTP::respond 401
} else {
HTTP::respond 401
}
}
HTTP::respond 403
log local0. "[IP::client_addr]:[TCP::client_port]: Sending 403 Response"
}
}
}
}
Surprisingly, this saves with no parsing errors but since this is 9.4.3,
class lookup does not work so I needed to convert this to using match
class and now I'm afraid that this won't actually do what I want it to
do, which is check to see if the userid is using a valid
password.I'm also not really certain whether the HTTP::respond 401 after the 'else' is needed but I have it in there now simply to include the 'else'. Can someone take a few moments to look this over and let me know where I need to make some changes?
- nitassEmployeemine is 10.2.3. for 9.4.3, can you try findclass [HTTP::username] users " " instead of class lookup?
[root@ve1023:Active] config b virtual bar list virtual bar { snat automap pool foo destination 172.28.19.79:80 ip protocol 6 rules myrule profiles { http {} tcp {} } } [root@ve1023:Active] config b class users list class users { "foo" { "acbd18db4cc2f85cedef654fccc4a4d8" } } [root@ve1023:Active] config b rule myrule list rule myrule { when HTTP_REQUEST { if { [HTTP::uri] contains "/uri/" } { if { [HTTP::header "Content-Type"] contains "text/xml" } { if { ! ( [IP::addr [IP::client_addr] equals 1.1.1.0/24] ) } { binary scan [md5 [HTTP::password]] H* password if { [class lookup [HTTP::username] users] equals $password } { log local0. "User [HTTP::username] authorized to access /uri/" } else { if { [string length [HTTP::password]] != 0 } { log local0. "User [HTTP::username] not authorized to access /uri/" } HTTP::respond 401 log local0. "[IP::client_addr]:[TCP::client_port]: Sending 401 Response" } } } } } } 1 [root@ve1023:Active] config curl -i http://172.28.19.79/uri/ -H "Content-Type: text/xml" -d "test=abc" HTTP/1.0 401 Unauthorized WWW-Authenticate: Basic realm="" Server: BigIP Connection: Keep-Alive Content-Length: 0 [root@ve1023:Active] config tail -f /var/log/ltm Apr 5 21:23:16 local/tmm info tmm[4797]: Rule myrule : 172.28.19.80:43504: Sending 401 Response 2 [root@ve1023:Active] config curl -i -u foo:foo http://172.28.19.79/uri/ -H "Content-Type: text/xml" -d "test=abc" HTTP/1.1 404 Not Found Date: Fri, 06 Apr 2012 04:24:54 GMT Server: Apache/2.2.3 (CentOS) Content-Length: 279 Content-Type: text/html; charset=iso-8859-1 ...snipped... [root@ve1023:Active] config tail -f /var/log/ltm Apr 5 21:24:25 local/tmm info tmm[4797]: Rule myrule : User foo authorized to access /uri/ 3 [root@ve1023:Active] config curl -i -u foo:wrong http://172.28.19.79/uri/ -H "Content-Type: text/xml" -d "test=abc" HTTP/1.0 401 Unauthorized WWW-Authenticate: Basic realm="" Server: BigIP Connection: Keep-Alive Content-Length: 0 [root@ve1023:Active] config tail -f /var/log/ltm Apr 5 21:24:59 local/tmm info tmm[4797]: Rule myrule : User foo not authorized to access /uri/ Apr 5 21:24:59 local/tmm info tmm[4797]: Rule myrule : 172.28.19.80:43591: Sending 401 Response
- mahnscNimbostratusThanks a lot! I'll give that a try.
- mahnscNimbostratusI'm going to have an opportunity to test this a little later on today but I was curious about the format of your class. I created a class in the Data Group List editor of the web console as a string that follows a format of " userid:md5sum_of_password " but yours looks like it has a format of: "userid" {"md5sum_of_password" }. Is your entry literally a string on a single line of: "foo" { "acbd18db4cc2f85cedef654fccc4a4d8" }
- nitassEmployeeif you use colon (:) as separator in findclass (findclass [HTTP::username] $::users ":"), data group should look like this.
[root@B3600-R67-S43:Active] config b class users list class users { "foo:acbd18db4cc2f85cedef654fccc4a4d8" }
- nitassEmployeein 9.4.3, $:: is required to reference data group.
- mahnscNimbostratusGreat. I had already made the edit to the separator so this is good news. Thanks again for your time!
- mahnscNimbostratusSo, things ended up not working too well for me. There were a couple issues. The first was that the client was sending a base64 encoded value for userid and password in the Authorization header, which my rule above doesn't seem to account to for. Do I need to decode this value first prior to doing the binary scan or am I just better off with storing the base64 value in the data group?
- mahnscNimbostratusDisregard the first question about decoding userid and password now that I've taken the time to re-read the wiki entries on HTTP::username and HTTP::password.
Recent Discussions
Related Content
DevCentral Quicklinks
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
Discover DevCentral Connects