Technical Forum
Ask questions. Discover Answers.
cancel
Showing results for 
Search instead for 
Did you mean: 

Rename default MRHsession cookie?

mike_aws_119486
Nimbostratus
Nimbostratus

I have a requirement to have APM Edge (at the Edge of the network facing internet) connecting to an APM appliance within the internal network which is providing Portal Access/SSO to apps.

 

I've configured APM Edge for 'Web Access' (as we don't want/need it rewriting stuff' and do strong authentication to RSA SecurID. I've configured the inside APM for 'Portal Access' (accessing multiple internal apps with URL rewriting) with AD authentication and SSO.

 

This doesn't work and I get an error about invalid session ID, I suspect what is happening is:

 

APM Edge issues MRHsession cookie for its session ID (e.g. ABC123) APM Edge forwards web connection to the Portal hosted by internal APM Internal APM issues MRHsession cookier for its session ID (e.g. XYZ987) overwriting original Next connection to APM Edge is rejected as MRHsession cookie contains an invalid session ID

 

Is there a way to use non default session cookie names such that the session cookies from the two APM platforms don't conflict?

 

For info the 'inside' F5 APM is replacing a very old Juniper SA for which this works ok (e.g. APM Edge forwards connection to portal on Juniper SA which does URL rewriting/App Publishing).

 

So technically it should be possible to do if only the internal APM didn't overwrite the external APM session cookie!

 

Many thanks in advance!

 

10 REPLIES 10

Well, architectural issues aside, the only way I can think of doing this is to use an iRule on your external F5 to rewrite the cookie name from the internal F5 for delivery to the client, and then rewrite it for delivery back to the internal F5. You could probably use a stream expression, also.

 

mike_aws_119486
Nimbostratus
Nimbostratus

Thanks, from an architectural perspective think of this as two completely seperate networks.

 

Network A wants to present a bunch of Apps to Network B so uses F5 APM to authenticate users to AD and present a portal to Network B with URL rewriting/SSO.

 

Network B wants to present the portal to external users over the internet and happens to also use F5 APM in their internet DMZ with RSA Auth.

 

Network A has no direct connection to the internet, Network B has no direct connection to the backend apps.

 

With different products it works (F5 APM in Network B + Juniper SA in Network A) the challenge is with both being F5.

 

I've tried writing an iRule today to capture session information but didn't seem to work. I did think some kind of rewrite of the backend cookies (but not the backend content) would be the solution but not entirely sure how to re-write the backend cookie?

 

Kevin_Stewart
F5 Employee
F5 Employee

If I may add, stacked APMs in an "air gap" configuration like this can be challenging. When you first connect to an APM VIP, you get that initial 302 redirect to /my.policy to start the session (and get the session cookie). So it's not just the cookies that are getting confused, but when you start an APM session on the external APM, then transit to the internal APM, that internal APM's initial 302 redirect will confuse the external APM. The way I've generally handled this is to:

 

  1. Use an iRule on the external APM to "manage and store" the session cookies from the internal APM. So when the internal APM sends its cookies, I store those in the external APM's user session and remove them from the stream. When a request comes in I remove the external APM's cookies from the stream and replace with the internal APM's cookies.

     

  2. Put the internal APM into "clientless-mode". This has the effect of disabling the initial 302 redirect to /my.policy, but also prohibits "blocking" mechanisms like logon forms, message boxes, and webtops. You can do pretty much anything else in the visual policy and all SSO should work. To get user credentials to the internal APM (in the absence of an internal logon form), I would request them on the external APM and send them as HTTP headers in the stream.

     

Here's a version of the iRule used on the external APM:

 

when HTTP_REQUEST_RELEASE {
     This event fires at the end of the access policy (just before releasing to the internal LTM) and
     blocks external APM session cookies from reaching the internal APM
    foreach externalcookie {"MRHSession" "LastMRH_Session" "F5_ST"} {
        HTTP::cookie remove $externalcookie
    }

     When initiating an APM policy, it sets a series of client session cookies. In this case the external
     APM captures the internal APM policy session cookies, stores them in the external session cache as 
     session variables (so that the internal session is "linked" to the external session), and removes
     them from the wire to the client. When the client makes a new request, the internal session tokens
     are retrieved from the external session cache and replayed to the internal APM as if the client
     sent them. This code section extracts the internal session tokens from the external session cache
     and inserts them as cookies to the internal APM.
    set cookielist [list]
    if { [ACCESS::session data get session.custom.internalMRH] ne "" } {
        lappend cookielist "MRHSession=[ACCESS::session data get session.custom.internalMRH];"
    }
    if { [ACCESS::session data get session.custom.internalLMRH] ne "" } {
        lappend cookielist "LastMRH_Session=[ACCESS::session data get session.custom.internalLMRH];"
    }
    if { [ACCESS::session data get session.custom.internalF5ST] ne "" } {
        lappend cookielist "F5_ST=[ACCESS::session data get session.custom.internalF5ST];"
    }

     reformat incoming Cookie header to include all of the locally managed cookies in one Cookie header
    set cookiehdr [HTTP::header "Cookie"]
    HTTP::header remove "Cookie"
    HTTP::header insert "Cookie" "[join $cookielist] $cookiehdr"

     The clientless-mode header tells the internal APM to create the session without the normal series of
     redirects. The remaining headers are used to transmit authenticated user data to the internal APM.
    HTTP::header replace "clientless-mode" 1

     This is the data that will be passing to the internal APM - define HTTP headers and values here
    HTTP::header replace AGUSER "joe.user"
    HTTP::header replace AGDOMAIN "CHARLIE"
}
when HTTP_RESPONSE {
     The internal APM's session initiation process sends a series of Set-Cookie headers. This code section
     captures those Set-Cookies, stores them in the external session cache, and removes them from the wire to the client.
    if { [HTTP::cookie exists "MRHSession"] } {
        ACCESS::session data set session.custom.internalMRH [HTTP::cookie value "MRHSession"]
        HTTP::cookie remove "MRHSession"
    }
    if { [HTTP::cookie exists "LastMRH_Session"] } {
        ACCESS::session data set session.custom.internalLMRH [HTTP::cookie value "LastMRH_Session"]
        HTTP::cookie remove "LastMRH_Session"
    }
    if { [HTTP::cookie exists "F5_ST"] } {
        ACCESS::session data set session.custom.internalF5ST [HTTP::cookie value "F5_ST"]
        HTTP::cookie remove "F5_ST"
    }
}

Then on the internal APM VIP, something like this:

 

when CLIENT_ACCEPTED {
     This command MUST be here
    ACCESS::restrict_irule_events disable 
}
when ACCESS_SESSION_STARTED {
     The authenticated user data is being transmitted from the external APM via HTTP headers. This section
     extracts those values and inserts them back into APM access policy session variables for use by the
     server side authentication process.
    if { [HTTP::header AGUSER] ne "" } {
        ACCESS::session data set session.logon.last.username [string trim [HTTP::header AGUSER]]
    }
}

It would conceivably be possible to not set clientless-mode on the internal APM VIP, and then handle all of the redirects and cookies in the external APM VIP's iRule, but that would be even less intuitive, and require not just changing the session cookies but also changing the redirects and internal APM URI patterns.

 

Hi Kevin, great Irule seems to work when having portal mode because all URLs are rewritten, when using LTM+APM mode (as you already mentioned) we need to map and redirect or rewrite all embedded F5 urls so they wont be processed by the external F5. We tried to redirect /my.policy to /policy and then at request release to rewrite it back to /my.policy and seems to work however the cookie header is empty when using your Irule. Do you have any guidance on how we could perform this correctly in APM+LTM mode with 2 F5 APM chained?

we cant modify the internal F5 so it needs to be fixed on the external F5

mike_aws_119486
Nimbostratus
Nimbostratus

Kevin,

 

Many thanks for your reply.

 

First for the dumb question, do I need to set the internal APM to clientless-mode in some way or is that already done in the iRule?

 

From what I read when APM is in clientless-mode you can't have a logon page....this presents a challenge as the internal APM currently has a policy which has:

 

Logon Page (Heavily customised with warnings/info etc) > AD Auth > SSO Mapping > Full Resource Access (Portal Access).

 

The APM at the edge has no access to the AD for auth and does RSA SecurID auth (e.g. users have to authenticate twice, once to RSA at the edge, then get the customised logon page with AD auth on the internal APM).

 

Is what you are suggesting to construct the customised logon page on the edge device to capture the AD credentials which would then be passed to the backend APM policy to authenticate?

 

Ideally I don't want to have to use clientless mode on the internal APM as then I could potentially use the VS/APM policy as is presented to internal users.

 

HAving said that this is what i tried:

 

Added a "Logon Page" to the end of the Edge APM policy to capture username/password Ammended the front end iRule to include:

 

This is the data that will be passing to the internal APM - define HTTP headers and values here set apmsessionuser [ACCESS::session data get "session.logon.last.username"] set apmsessionpass [ACCESS::session data get "session.logon.last.password"] HTTP::header replace AGUSER $apmsessionuser HTTP::header replace AGPASS $apmsessionpass

Removed the Logon page from the internal APM policy Ammended the internal iRule to include:

 

The authenticated user data is being transmitted from the external APM via HTTP headers. This section extracts those values and inserts them back into APM access policy session variables for use by the server side authentication process. if { [HTTP::header AGUSER] ne "" } { ACCESS::session data set session.logon.last.username [string trim [HTTP::header AGUSER]] if { [HTTP::header AGPASS] ne "" } { ACCESS::session data set session.logon.last.password [string trim [HTTP::header AGPASS]] } }

However I get is "Your session is finished. Logged out succesfully".

 

If I look at the list of sessions on the back-end it is correctly showing the username captured in that second logon page so that is coming across, but in the Access report the username deoesn't show and the report is as follows:

 

2014-01-16 18:16:09 Following rule 'fallback' from item 'Start' to item 'AD Auth' Common

 

2014-01-16 18:16:09 AD agent: ENTER Function executeInstance Common

 

2014-01-16 18:16:09 AD module: ENTER Function authenticateUser Common

 

2014-01-16 18:16:09 AD module: authentication with '' failed: empty password detected (-1) Common

 

2014-01-16 18:16:09 AD module: authenticate(): empty password detected (-1) Common

 

2014-01-16 18:16:09 AD module: LEAVE Function authenticateUser Common

 

2014-01-16 18:16:09 AD agent: Auth (logon attempt:0): authenticate with 'testuser' failed Common

 

2014-01-16 18:16:09 AD agent: LEAVE Function executeInstance Common

 

2014-01-16 18:16:09 Executed agent '/Common/InternalPortal-Test_act_active_directory_ag', return value 0 Common

 

2014-01-16 18:16:09 Following rule 'fallback' from item 'AD Auth' to ending 'Deny' Common

 

2014-01-16 18:16:09 Access policy result: Logon_Deny

 

So the 'testuser' is coming across in the iRules....

 

Any further ideas/suggestions would be very much appreciated.

 

mike_aws_119486
Nimbostratus
Nimbostratus

OK have got a bit further....

 

Firstly realised I could not get the password variable because its secure and was falling fowl of the same issue as in this question:

 

https://devcentral.f5.com/questions/cant-get-apm-secure-session-variable-value-in-irule

 

So what I did was use VPE to configure an expression:

 

session.logon.last.password1 = return "[mcget -secure {session.logon.last.password}]"

Then changed the initial iRule to:

 

This is the data that will be passing to the internal APM - define HTTP headers and values here set apmsessionuser [ACCESS::session data get "session.logon.last.username"] set apmsessionpass [ACCESS::session data get "session.logon.last.password1"] HTTP::header replace AGUSER $apmsessionuser HTTP::header replace AGPASS $apmsessionpass

I can now see it authenticating ok on the internal APM, however all I get from clients is "Page Cannot Be Displayed" so looks like the portal access/rewrite isn't necessarily working properly!

 

APM logs from the front end as follow:

 

2014-01-16 19:46:04 Username 'testuser' Common 2014-01-16 19:46:13 Username 'testuser' Common 2014-01-16 19:46:13 Following rule 'fallback' from item 'Variable Assign' to ending 'Allow' Common 2014-01-16 19:46:13 Access policy result: LTM+APM_Mode

APM logs from the internal APM as follows:

 

2014-01-16 19:49:48 Following rule 'fallback' from item 'Start' to item 'AD Auth' Common 2014-01-16 19:49:48 AD agent: ENTER Function executeInstance Common 2014-01-16 19:49:48 AD Agent: invalid user password ciphertext Common 2014-01-16 19:49:48 AD module: ENTER Function authenticateUser Common 2014-01-16 19:49:48 AD module: authenticate with 'testuser@DOMAIN.COM' successfully Common 2014-01-16 19:49:48 AD module: LEAVE Function authenticateUser Common 2014-01-16 19:49:48 AD agent: Auth (logon attempt:0): authenticate with 'testuser' successful Common 2014-01-16 19:49:48 AD agent: LEAVE Function executeInstance Common 2014-01-16 19:49:48 Executed agent '/Common/InternalPortal-Test_act_active_directory_auth_ag', return value 0 Common 2014-01-16 19:49:48 Following rule 'Successful' from item 'AD Auth' to item 'SSO Credential Mapping' Common 2014-01-16 19:49:48 Executed agent '/Common/InternalPortal-Test_act_sso_credential_mapping_1_ag', return value 0 Common 2014-01-16 19:49:48 Following rule 'fallback' from item 'SSO Credential Mapping' to item 'Full Resource Assign' Common 2014-01-16 19:49:48 Webtop '/Common/InternalPortal_SSOTest_webtop' assigned Common 2014-01-16 19:49:48 Executed agent '/Common/InternalPortal-Test2_act_full_resource_assign_ag', return value 0 Common 2014-01-16 19:49:48 Following rule 'fallback' from item 'Full Resource Assign' to ending 'Allow' Common 2014-01-16 19:49:48 StartURI from webtop: https://portal.domain.com Common 2014-01-16 19:49:48 Access policy result: Web_Application Common 2014-01-16 19:49:48 Executed agent '/Common/InternalPortal-Test2_end_allow_ag', return value 0 Common 2014-01-16 19:49:48 Session variable 'session.ad./Common/InternalPortal-Test2_act_active_directory_auth_ag.actualdomain' set to 'DOMAIN.COM' Common 2014-01-16 19:49:48 Session variable 'session.ad./Common/InternalPortal-Test2_act_active_directory_auth_ag.authresult' set to '1' Common 2014-01-16 19:49:48 Session variable 'session.ad./Common/InternalPortal-Test2_act_active_directory_auth_ag.errmsg' set to ' ' Common 2014-01-16 19:49:48 Session variable 'session.ad.last.actualdomain' set to 'DOMAIN.COM' Common 2014-01-16 19:49:48 Session variable 'session.ad.last.authresult' set to '1' Common 2014-01-16 19:49:48 Session variable 'session.ad.last.errmsg' set to ' ' Common 2014-01-16 19:49:48 Session variable 'session.assigned.resources.pa' set to '/Common/InternalPortal_SSOTest_pa_res' Common 2014-01-16 19:49:48 Session variable 'session.assigned.uuid' set to 'tmm.uuid./Common/InternalPortal-Test2.' Common 2014-01-16 19:49:48 Session variable 'session.assigned.webtop' set to '/Common/InternalPortal_SSOTest_webtop' Common 2014-01-16 19:49:48 Session variable 'session.logon.page.errorcode' set to '0' Common 2014-01-16 19:49:48 Session variable 'session.policy.result' set to 'allow' Common 2014-01-16 19:49:48 Session variable 'session.policy.result.start_uri' set to '/f5-w-68747410723a2f2f706f7274616c2e545972766576652e707269$$/' Common 2014-01-16 19:49:48 Session variable 'session.policy.result.webtop.type' set to 'web_application' Common 2014-01-16 19:49:48 Session variable 'session.sso.token.last.password' set to '**********' Common 2014-01-16 19:49:48 Session variable 'session.sso.token.last.username' set to 'testuser' Common 2014-01-16 19:49:48 Session variable 'session.webtop.customization.group' set to '/Common/InternalPortal_SSOTest_webtop_customization'

At a loss now.....

 

You should have an option in the portal access object to turn on logging. It may help.

mike_aws_119486
Nimbostratus
Nimbostratus

Just to update anyone interested we engaged F5 consultancy who developed an iRule for the outer APM which deals with the session cookie name and effectively passes all traffic to the back-end APM once a user authenticates at the frontend.

 

Obviously as it been developed by F5 consultancy I dont think its appropriate to share here but thought I'd post that it can be done!

 

Hi Mike, do you have this iRule?