Forum Discussion
APM Open a second startup browser after the webtop portal launch
Hello, I'm using a Portal access Webtop to redirect users to the corporate startup page after the access Policy is completed. the issue I'm having with this method is that the APM standard webtop startup page does not open while users need to access manually some webtop like application tunnel or some other specific applications not accessible through the corporate page. how can I have both pages opened the same time after the access policy is completed, the corporate startup page should be rewritten by the APM also the corporate statup page is published in APM webtop page so if there's a method to automatically click that webtop, that would fix my issue.
thank you for your help
13 Replies
- Kevin_Stewart
Employee
Okay, I'm going to file this one under oddball configs, but I think I have something that will work. Tested on 11.5 so your mileage may vary.
The basic config is a layered set of VIPs: external LTM HTTPS VIP with SSL offload, generic STREAM profile, and an iRule, and internal APM HTTP VIP with webtop and portal configuration. You can still set the secure flag in the access policy because the external interface is HTTPS.
client -> LTM VIP -> APM VIPAnd now the iRule (applied at the external LTM VIP):
when HTTP_REQUEST { STREAM::disable if { [HTTP::uri] starts_with "/vdesk/webtop.eui?webtop=" } { if { [ACCESS::session data get -sid [HTTP::cookie value MRHSession] session.custom.trigger] ne 1 } { set catch 1 ACCESS::session data set -sid [HTTP::cookie value MRHSession] session.custom.trigger 1 } } virtual simple-vs } when HTTP_RESPONSE { if { [info exists catch] } { unset catch STREAM::expression {@@ @} STREAM::enable } }The idea is this:
-
If the URI starts with "/vdesk/webtop.eui?webtop=", a standard webtop invocation, check the value of a custom session variable. If it's already set, do nothing. If it isn't set, create a temporary "catch" variable. The session variable prevents the second tab from opening multiple times.
-
Use the virtual command in the HTTP_REQUEST to send the traffic to the internal APM VIP.
-
In the HTTP_RESPONSE event, if the catch variable exists, unset it and then use the STREAM profile to add a little piece of JavaScript to the end of the webtop document. In this case it's the "F5_Invoke_open" function that's normally used to launch links within the webtop. The only thing you need to change here is the URL that it's going to open. You can use the real value or the obfuscated URL. Either appear to work. Also, because you'll be using JavaScript to open a window without user intervention, most browsers will see that as a popup and warn you, so you'd need to set this as a trusted site to prevent that warning message.
And of course you may still need to alter to fit your exact use case.
-
- Madiw_114772
Nimbostratus
Kevin, Thanks a lot for your reply I tried a different approach this week-end and it's working fine : I'm injecting a javascript that open a second browser with the rewritten link of my resource but I have currently an issue with the sso for the resource. It seems that the sso mapping that I defined in the access policy doesn't apply to the application when I call it with the javascript, it does work when I click the webtop.
Any hint about that ? also, any suggestion to improve the irule is welcomed. I'll give a try to your solution later.
when CLIENT_ACCEPTED { ACCESS::restrict_irule_events disable } when RULE_INIT { set web_code " type='text/javascript'> type='text/javascript'> window.open('https://portal.corporate.com/f5-w-687474703a2f2f676f6f676c652e636f6d$$/')
" }
when HTTP_REQUEST { set activate_js 0 if { [HTTP::uri] ends_with "/vdesk/webtop.eui?webtop=/Cert/My_Test_webtop&webtop_type=webtop_full" } { log local0. "URI match full webtop" Don't allow data to be chunked if { [HTTP::version] eq "1.1" } { if { [HTTP::header is_keepalive] } { HTTP::header replace "Connection" "Keep-Alive" } HTTP::version "1.0" } set activate_js 1
} } when HTTP_RESPONSE { if {$activate_js equals "1"} { if { [HTTP::header Content-Type] starts_with "text/html" } { if { [HTTP::header exists "Content-Length"] } { log local0. "content length: [HTTP::header {Content-Length}]" set content_length [HTTP::header "Content-Length"] } else { set content_length 1000000000 } log local0. "Collecting $content_length bytes" if { $content_length > 0 } { HTTP::collect $content_length } } } } when HTTP_RESPONSE_DATA { set web_code " type='text/javascript'> type='text/javascript'> window.open('https://portal.corporate.com/f5-w-687474703a2f2f676f6f676c652e636f6d$$/')" my trigger is 8888, it could be anything if { [HTTP::payload] contains "8888" }{ log local0. "Payload didn't contain $::exist_search!" set idx [string last "" [HTTP::payload]] if { -1 == $idx } { set idx [string last "" [HTTP::payload]] } log local0. "html end tag found at $idx" if { -1 == $idx } { set offset [HTTP::payload length] } else { set offset $idx } HTTP::payload replace $offset 0 $web_code log local0. "HTTP_REQUEST_DATA good" } }
- Madiw_114772
Nimbostratus
Code when CLIENT_ACCEPTED { ACCESS::restrict_irule_events disable } when RULE_INIT { set web_code " "}
when HTTP_REQUEST { set activate_js 0 if { [HTTP::uri] ends_with "/vdesk/webtop.eui?webtop=/Cert/My_Test_webtop&webtop_type=webtop_full" } { log local0. "URI match full webtop" Don't allow data to be chunked if { [HTTP::version] eq "1.1" } { if { [HTTP::header is_keepalive] } { HTTP::header replace "Connection" "Keep-Alive" } HTTP::version "1.0" } set activate_js 1 } } when HTTP_RESPONSE { if {$activate_js equals "1"} { if { [HTTP::header Content-Type] starts_with "text/html" } { if { [HTTP::header exists "Content-Length"] } { log local0. "content length: [HTTP::header {Content-Length}]" set content_length [HTTP::header "Content-Length"] } else { set content_length 1000000000 } log local0. "Collecting $content_length bytes" if { $content_length > 0 } { HTTP::collect $content_length } } } } when HTTP_RESPONSE_DATA { set web_code " " my trigger is 8888, it could be anything if { [HTTP::payload] contains "8888" }{ log local0. "Payload didn't contain $::exist_search!" set idx [string last "" [HTTP::payload]] if { -1 == $idx } { set idx [string last "" [HTTP::payload]] } log local0. "html end tag found at $idx" if { -1 == $idx } { set offset [HTTP::payload length] } else { set offset $idx } HTTP::payload replace $offset 0 $web_code log local0. "HTTP_REQUEST_DATA good" } } - Kevin_Stewart
Employee
In a round-about way, we doing about the same thing. Interesting that yours works in a single VIP while the STREAM requires a layered VIP. I would contend that the STREAM is probably faster here, and wouldn't require any of the payload buffering, and HTTP 1.1 and chunking management. In any case, if you have a chance to try my version, please do and test SSO. I'll dig in if it doesn't work.
- Madiw_114772
Nimbostratus
Kevin,
Your solution is working great...In fact sso is working for both irules, I found that the sso config was broken for this specific application.
I would like to use your solution but I need to add one more criteria to identify the user that are connecting and bring up the window depending on who's connecting.
In my irule, I'm looking the payload and I the webtop name that is assigned only to the profile that should see the second windows
do you have an hint on how I can do it on your irule without leveraging HTTP::payload.if { [HTTP::payload] contains "8888" }thanks
- Kevin_Stewart
Employee
A few questions:
-
Is "8888" actually in the HTTP payload, or in a response header? If the former, then you really don't have much choice but to use HTTP::payload.
-
Could you store the information (user and webtop assignment) in session variables and check those in the request or response? Instead of looking at response payload?
-
- Madiw_114772
Nimbostratus
- the 8888 is in the payload
- Sure, I could do that, I have a ldap attribute that I'm looking in the access policy and that attribute allows me to assign resources. I identified the session variable for that attribute «session.ldap.last.attr.nsrole», so I can call it in the response and use it as a trigger for the stream invoking. do you have a quick example for using APM variables in irule ...otherwise, I'll find out.
thank you
- Madiw_114772
Nimbostratus
I tested the iRule and the second browser is still opening even if the account doesn't have the good nsrole value. For testing, I modified the Irule as follow
when HTTP_REQUEST { STREAM::disable if { [HTTP::uri] starts_with "/vdesk/webtop.eui?webtop=" } { if { [ACCESS::session data get -sid [HTTP::cookie value MRHSession] session.custom.trigger] ne 1 } { set nsrole1 "[ACCESS::session data get session.ldap.last.attr.nsrole]" log local0. "nsrole1 = $nsrole1" if { [ACCESS::session data get -sid [HTTP::cookie value MRHSession] session.ldap.last.attr.nsrole] contains "f5_full" } { set catch 1 ACCESS::session data set -sid [HTTP::cookie value MRHSession] session.custom.trigger 1 } } } virtual /Cert/MY_test_VS } when HTTP_RESPONSE { set nsrole "[ACCESS::session data get session.ldap.last.attr.nsrole]" log local0. "nsrole = $nsrole" if { [info exists catch] } { unset catch STREAM::expression {@@ @} STREAM::enable } }and logs show nsrole and nsrole1 entries with the trigger not in the attribute but the second browser still open
May 8 14:28:41 fb001 info tmm7[5710]: Rule /Cert/JS_injection_layered_VIP_CERT : nsrole = | cn=cdms_abc_general_consumer,o=abc | cn=cdms_cc_consumer,o=abc | cn=containerdefaulttemplaterole,o=abc | cn=containerdefaulttemplaterole,o=abc.com,o=abc | cn=dn-affiliation management,o=abc | =abc | cn=dn-abcll centres,o=abc | cn=dn-ccma,o=abc | cn=dn-managersunion,o=abc | cn=dn-users,o=abc | cn=elearning,o=abc.com,o=abc | cn=f5_abcllcentre,o=abc | May 8 14:28:41 fb001 info tmm2[5710]: Rule /Cert/JS_injection_layered_VIP_CERT : nsrole1 = | cn=cdms_abc_general_consumer,o=abc | cn=cdms_cc_consumer,o=abc | cn=containerdefaulttemplaterole,o=abc | cn=containerdefaulttemplaterole,o=abc.com,o=abc | cn=dn-affiliation management,o=abc | ,o=abc | cn=dn-abcll centres,o=abc | cn=dn-ccma,o=abc | cn=dn-managersunion,o=abc | cn=dn-users,o=abc | cn=elearning,o=abc.com,o=abc | cn=f5_abcllcentre,o=abc |I'm looking how catch is set to 1 if the condition below is not matched
if { [ACCESS::session data get -sid [HTTP::cookie value MRHSession] session.ldap.last.attr.nsrole] contains "f5_full" } - Madiw_114772
Nimbostratus
Just an update for future readers, The irule above is correct and everything is working fine.
The issue was that I missed that my first irule was still applied to the APM VS so, when I removed it, this irule above worked fine.
method 1 : irule using HTTP::payload applied to APM VS client -> APM VIP method 2 : irule with layered VIPs applied to LTM VS client -> LTM VIP -> APM VIP - Madiw_114772
Nimbostratus
Kevin,
One more thing I found that this scenario (client » LTM VIP » APM VIP) is breaking the application tunnel services that are already configured. I'm getting an error message «failed to download configuration» and in the client logs, I see
2014-05-16,12:35:25:726, 9348,13952,HOST, 0,,,, starting local TunnelServer 2014-05-16,12:36:06:917, 9348,13952,HOST, 1, \HostCtrl.cpp, 1691, CHostCtrl::OnTimer(), TUNNEL_SERVER_READY_CHECK - configuration read timed out 2014-05-16,12:36:06:917, 9348,13952,HOST, 1, \HostCtrl.h, 1447, CHostCtrl::Failed, Téléchargement de configuration impossible (error: 0) 2014-05-16,12:36:06:918, 9348,13952,HOST, 1, \HostCtrl.h, 1478, CHostCtrl::Failed, Firing event (message: download configuration impossible) 2014-05-16,12:39:57:293, 9348,13952,SUPERHOST, 2, \BrowserContainer.cpp, 281, CBrowserContainer::CleanupHTMLDocument, Failed to get IHTMLDocument2 pointer, error 0x1 2014-05-16,12:40:50:740, 14528,18368,PLUGINHOST, 0,,,, Request to install/update SuperHost Class 2014-05-16,12:40:51:017, 14528,18860,PLUGINHOST, 2, \urSmartUpdateEx.cpp, 520, USmartUpdateEx::RunObjectProc(), need not install/update control,Any hints ? thanks
- Kevin_Stewart
Employee
You're referring to network access configurations? SSL VPNs? - Madiw_114772
Nimbostratus
I'm referring to app tunnel thanks - n0vac_65442
Nimbostratus
Layered VIP approach also prevents Citrix and RDP resources from launching. Is there any alternative way to inject some html code to APM response?
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
* 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