Learn F5 Technologies, Get Answers & Share Community Solutions Join DevCentral

Filter by:
  • Solution
  • Technology
Answers

Not Returning back to the current loadbalancer url from external service

Hi All,

For achieving the below use case i have written the following service.From the current url calling the ezternal Cookiegenerator.html service and SMCookie got generated.

But it is not returning to the current loadbalancer url. After pressing enter button only it is returning to current url(finalusers.html)

Please advise on this i tried with HTTP::retry in HTTP_RESPONSE.

UseCase: 1) Enter LoadBalancer url http://xmppwst.airservices.eds.com/OAuthDemo/finalusers.html i.e( Actually it is mapped to http://usclspcit192.airservices.eds.com/OAuthDemo/finalusers.html”)

2) Enter userid/password (testuser1/p@ssw0rd)

3) Grab userid/Password(i.e Authorization Header) OR SMCOOKIE

4) Call http://xmppt.airservices.eds.com:8080/TestBasicAuth/cookiegenerator.html with Authorization Header OR SMCOOKIE (Note user shouldn’t it is redirected to 208 box always we need to show loadbalancer url (http://usclssoat208.airsoatest.airservices.eds.com/TestBasicAuth/cookiegenerator.html)

5) Siteminder Authentication returns the Siteminder Cookie

6) AT f5 Grab the SMCookie from 208 box

7) http://xmppwst.airservices.eds.com/OAuthDemo/finalusers.html with SMCookie

when CLIENT_ACCEPTED { set cookie 1 set gotpath 0 set smsession "" set def_pool [LB::server pool] set sm 0
}

when HTTP_REQUEST { if { $gotpath == 0 && $sm == 0 } { pool Rachel_test_8080 HTTP::uri /OAuthDemo/cookiegenerator.html

         if { [HTTP::header exists "Authorization"] } {
          set authzheaders "Authorization: [HTTP::header value Authorization]"
         }

          set request_headers [HTTP::request]  
          set gotpath 1                           

  } elseif { $sm == 1 } {
          pool $def_pool
  }
}

when HTTP_RESPONSE {

 log local0. "http_response: cookie:test22=$cookie; status:test22=[HTTP::status]; sm=[HTTP::cookie exists "SMSESSION"]"

 if { [HTTP::cookie exists "SMSESSION"] } {
    set smsession "SMSESSION=[HTTP::cookie value SMSESSION]"
    set sm 1
  }  

 if { [HTTP::status] == 404} {
    HTTP::retry $smsession
 }

} Regards, Praque

0
Rate this Question

Answers to this Question

placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

It may be easiest to describe this "sideband" process in terms of flow, as there are distinct differences between how a v11 sideband call works and how HTTP::retry works to accomplish the same thing. First a picture:

Image Text

What you see here is the v11 sideband process. It produces a "blocking" request to a remote service. The client request arrives at the VIP (forward momentum), is stopped temporarily to issue the sideband call, and then allowed to move forward to the application.

Image Text

This next image is closer to what HTTP::retry is doing to accomplish the same thing. The biggest difference here is momentum and direction. Instead of stopping/blocking the client request to make the sideband call, the client request is saved, and then redirected/shifted to another resource with the same forward momentum. The return response from the "lookup" service is treated the same way as a response from the application. When the lookup service then returns with its data, the original request and default pool are re-assigned and HTTP::retry "flips" the egress momentum and sends it back out to the real application server. The important take away here is that the lookup service triggers the same HTTP_RESPONSE event that the application does, so you have to take great care to make sure you know which is which. Here's a streamlined and simplified version of what that looks like:

when CLIENT_ACCEPTED {
    ## Get the defined pool for this VIP
    set default_pool [LB::server pool]

    ## Set an initial lookup flag
    set lookup 1
}
when HTTP_REQUEST {
    ## On first request (lookup flag exists) perform lookup
    if { [info exists lookup] } {

        ## Save the original request
        set request [HTTP::request]

        ## Change URI for sideband lookup
        HTTP::uri "/ldaplookup.php?find=bob.user"

        ## Change pool to point to sideband web service
        pool local-pool-single
    }
}
when HTTP_RESPONSE {
    ## If response from web service
    if { [info exists lookup] } {

        ## Unset flag to prevent subsequent lookups
        unset lookup

        ## Collect the payload from the lookup
        HTTP::collect [HTTP::header Content-Length]
    }
}
when HTTP_RESPONSE_DATA {
    ## Payload of lookup exists here
    log local0. [HTTP::payload]

    ## Reset to the default pool
    pool $default_pool

    ## Retry the original request
    HTTP::retry $request
}

So looking at this example, take notice of the following details:

  1. It's using a local variable in the CLIENT_ACCEPTED event to control lookup service flow. On initial TCP handshake, the flag is set allowing the lookup to happen. The response event from that lookup unsets the flag so that the lookup doesn't happen again. Since this is being done in the CLIENT_ACCEPTED event, you can guarantee that the lookup will not happen more than once per TCP session, but that it WILL happen in each new TCP session. If you need it to only happen once for the life of the application session, then you need to devise another way to save this state (ie. a unique browser cookie or session table entry that indicates a completed lookup). You've stated that the initial client request could either come with username/password data or an SMSESSION cookie (which is what you're going to get/renew in the sideband call). You then could:

    • Set a new/different cookie in the browser on first response to the client to indicate that the lookup is complete (and that the current SMSESSION cookie is valid)

    • Create a session table entry mapped to the SMSESSION cookie that indicates that the lookup is complete (by virtue of its existence)

    • Simply let the lookup happen on every new TCP session.

  2. The values from the lookup will be available in the HTTP_RESPONSE_DATA event. Once you initiate the HTTP::retry command, a new HTTP request will happen. Remember that this is an egress event, so that if you need to do something based on the client request (ingress), you'll need to save the payload contents and use them in another event (though technically you could parse the original request in the local variable).

1
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

Hi Pretty confusing this. Who would set the cookie ? Is this all on the same virtual server? Returning to the old Path is normally done using a HTTP redirect. Or http response 301 You reset your vars when client connects which is for every request. Not sure I get the complete picture. Regards Wiesmann

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
when CLIENT_ACCEPTED { 
    set cookie 1 set gotpath 0 
    set smsession "" 
    set def_pool [LB::server pool] 
    set sm 0  
    } 
when HTTP_REQUEST { 
    if { $gotpath == 0 && $sm == 0 } {
        pool Rachel_test_8080 
        [HTTP::uri] /OAuthDemo/cookiegenerator.html
        set request_headers [HTTP::request]
      if { [HTTP::header exists "Authorization"] } {
          set authzheaders "Authorization: [HTTP::header value Authorization]" 
          }
          set gotpath 1 
          } elseif { 
                $sm == 1 } {
                pool $def_pool  
                } 
        } 
when HTTP_RESPONSE { 
log local0. "http_response: cookie:test22=$cookie; status:test22=[HTTP::status]; sm=[HTTP::cookie exists "SMSESSION"]"
    if { [HTTP::cookie exists "SMSESSION"] } { 
        set smsession "SMSESSION=[HTTP::cookie value SMSESSION]"
        set sm 1 
        } 
    if { [HTTP::status] == 404} { 
        HTTP::retry $smsession 
        } 

I tried to format the irule a bit better, but it still dosn't make sense to me.

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

Looking at: "set authzheaders" Why do you set a Variable you never reuse again ? What is the purpose of this.

First request... will select the Pool Rachel_test_8080 (will that Pool accept the Request planned for the other server ?

when HTTP_REQUEST { if { $gotpath == 0 && $sm == 0 } { pool Rachel_test_8080

I would think a connection flow diagram would help to understand what you plan to do.

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

Thanks Juerg. Please find the details required. i have removed the authorisation header.

Steps: 1) User Hitting LoadBalancer URL in Browser ("http://xmppwst.airservices.eds.com/OAuthDemo/finalusers.html") This is default POOL(Rachel_Test).

2) Siteminder challenges the user, Enter userid/password.

3) Grap userid/password using irule and post to another loadbalancer url(http://xmppt.airservices.eds.com/OAuthDemo/cookiegenerator.html) Cookie generator authenticate the user and return the SiteminderCookie(SMCookie). Note this loadbalancer url is mapped to(Rachel_Test_8080).

4) After grapping the SMCookie and landing page shown to user(http://xmppwst.airservices.eds.com/OAuthDemo/finalusers.html). (ie default pool url(Rachel_Test))

when CLIENT_ACCEPTED { set cookie 1 set gotpath 0 set smsession "" set def_pool [LB::server pool] set sm 0
} when HTTP_REQUEST { if { $gotpath == 0 && $sm == 0 } { pool Rachel_test_8080 [HTTP::uri] /OAuthDemo/cookiegenerator.html set request_headers [HTTP::request] set gotpath 1 } elseif { $sm == 1 } { pool $def_pool
} } when HTTP_RESPONSE { log local0. "http_response: cookie:test22=$cookie; status:test22=[HTTP::status]; sm=[HTTP::cookie exists "SMSESSION"]" if { [HTTP::cookie exists "SMSESSION"] } { set smsession "SMSESSION=[HTTP::cookie value SMSESSION]" set sm 1 } if { [HTTP::status] == 404} { HTTP::retry $smsession }

0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER
when CLIENT_ACCEPTED { 
    set cookie 1 set gotpath 0 
    set smsession "" 
    set def_pool [LB::server pool] set sm 0 
} 
when HTTP_REQUEST { 
    if { $gotpath == 0 && $sm == 0 } { 
        pool Rachel_test_8080 
        [HTTP::uri] /OAuthDemo/cookiegenerator.html 
        set request_headers [HTTP::request] 
        set gotpath 1 
     } elseif { 
            $sm == 1 } { 
            pool $def_pool
    } 
    } 
when HTTP_RESPONSE { 
    log local0. "http_response: cookie:test22=$cookie status:test22=[HTTP::status]; sm=[HTTP::cookie exists "SMSESSION"]" 
    if { [HTTP::cookie exists "SMSESSION"] } { 
        set smsession "SMSESSION=[HTTP::cookie value SMSESSION]" 
        set sm 1 
        } 
        if { [HTTP::status] == 404} { 
        HTTP::retry $smsession 
        } 

So I understand: Rachel_Test is the Siteminder Pool... Correct ? "You should look for a girl named Sideminder I think ;-)"

Is, "xmppwst.airservices.eds.com" and "xmppt.airservices.eds.com" resolving on the same virtual ?

Should the Browser go to xmppt.airservices.eds.com or should the connection flow go User BIG-IP1 (VS xmppt.airservices.eds.com) pool Rachel_Test_8080 which is BIG-IP2 (VS xmppt.airservices.eds.com) ?

Normally we build szenarios with Authentication Virutuals using Redirects. In a Redirect you may pack in, Username&Password&originalURI, and on the second BIG-IP you would store this, detect successful login and initiate a Redirect back to BIG-IP 1 (originalURI) including the Cookie aso. Attention, cookie will not be submitted to another Domain, so Authentication should be made doing a redirect to same host but different URI "/OAuthDemo/cookiegenerator.html" and if the URI in a request is /OAuthDemo/cookiegenerator.html you will select the other pool with the authentication Server.

when HTTP_REQUEST {                
    if { [HTTP::uri] ends_with "/OAuthDemo/cookiegenerator.html"} { 
         pool Rachel_test_8080 } 
         else { 
               pool $def_pool
                } 
0
placeholder+image
USER ACCEPTED ANSWER & F5 ACCEPTED ANSWER

Hi Kevin,

Now cookie value returning from external url to current url using the following code.

when CLIENT_ACCEPTED { log local0. "enter client_accepted:" set cookie 1 set gotpath 0 set smsession "" set def_pool [LB::server pool] set sm 0
}

when HTTP_REQUEST { log local0. "enter http_request:: gotpath=$gotpath" if { $gotpath == 0 && $sm == 0 } {
log local0. "inside _Rachel_8080:" pool Rachel_test_8080 HTTP::uri /OAuthDemo/cookiegenerator.html log local0. "gotpath:::$gotpath;uri:::HTTP::uri /OAuthDemo/cookiegenerator.html" set request_headers [HTTP::request] log local0. "host:::[HTTP::host]" log local0. "request_headers:::$request_headers" set gotpath 1
} elseif { ([LB::server pool] ne $def_pool) } { pool $def_pool }
} when HTTP_RESPONSE { log local0. "http_response: cookie:=$cookie; status:=[HTTP::status]; sm=[HTTP::cookie exists "SMSESSION"]" if { ([LB::server pool] ne $def_pool) && [HTTP::cookie exists "SMSESSION"] } { set smsession "SMSESSION=[HTTP::cookie value SMSESSION]" log local0. "smsession##$smsession" set sm 1
}
}

Regards, praque

0