Author Archives trententtye

Citrix Storefront – Performance Testing and Tuning – Part 3 – PerfMon Counters, browser logon

2017-06-01
/ /
in Blog
/

In looking at the performance of the Citrix Storefront Server, one of the thing I want is to understand what Storefront is doing at each stage of a session life cycle.  There are two session-types that I’m curious about, a web browser based connection and a PNA connection.  I’m going to examine a web browser based connection first.

Using my powershell script to simulate a user connection I put ‘pauses’ between each stage.  I then setup Perfmon to capture counters from the following objects:

I’ve added 6 farms to the storefront server to examine the load “in a real world” environment as Storefront does do some magic with concurrent enumeration.  What I love that Citrix has done, is actually time the transactions AND gives you the ‘rate’ the transactions are occurring at.  This will make it much easier to baseline what your load is vs how I had to do it to measure the ‘rates’ for Web Interface.


$stage = “Initial Connection”
$store = “http://storefront.bottheory.local/Citrix/StoreWeb/”

So for a web browser based connection, I ‘connected’ to the site and saw nothing.  Storefront does very little work for the initial connection.


$stage = “Client Configuration”
$store + “Home/Configuration”

Result:

This request is to get the client configuration.  Essentially, it pulls down an xml file from the store containing important links to various locations in Storefront. Again, no perf counter seems to occur and it doesn’t seem to generate any load.


$stage = “Get Authentication Methods”
$store + “Resources/List”

 

So this command starts to get a little exciting.  It’s a bit of a misnomer to call it “Resources/List” as it doesn’t actually return resources, yet.  It returns the challenge to logon.  We get our first Peformance Counter hit.

The four counters that register are

“Citrix Receiver for Web\List resources Calls / second”
“Citrix Receiver for Web\List resources Average Time (microseconds)”
“Citrix Delivery Services Web Application(dazzleresources:list:get:_citrix_store)\Controller Action Calls / second”
“Citrix Delivery Services Web Application(dazzleresources:list:get:_citrix_store)\Controller Action Average Time (Microseconds)”
Results:
List resources Calls / second: 1
List resources Average Time (microseconds): 3,714
(dazzleresources:list:get:_citrix_store)\Controller Action Average Time (Microseconds): 607
(dazzleresources:list:get:_citrix_store)\Controller Action Calls / second: 1


$stage = “Get Auth Methods”
$store + “Authentication/GetAuthMethods”

Response:

Another exciting call.  This call hits these four performance counters:

“Citrix Delivery Services Web Application(authservice:tokenservices:post:_citrix_authentication)\Controller Action Calls / second”
“Citrix Delivery Services Web Application(authservice:tokenservices:post:_citrix_authentication)\Controller Action Average Time (Microseconds)”
“Citrix Delivery Services Web Application(protocols:choices:post:_citrix_authentication)\Controller Action Calls / second”
“Citrix Delivery Services Web Application(protocols:choices:post:_citrix_authentication)\Controller Action Average Time (Microseconds)”

Results:
(protocols:choices:post:_citrix_authentication)\Controller Action Calls / second: 1
(protocols:choices:post:_citrix_authentication)\Controller Action Average Time (Microseconds) : 488
(authservice:tokenservices:post:_citrix_authentication)\Controller Action Calls / second: 1
(authservice:tokenservices:post:_citrix_authentication)\Controller Action Average Time (Microseconds): 138

The Controller Action Calls /second was “1”, obviously I’m doing just a single test.  For the action average time I got 711 microseconds.  Extremely fast.


$stage = “Domain Pass-Through and Smart Card Authentication”
$store + “DomainPassthroughAuth/Login”

Response:

Two more perf counters hit (rate + time):

Citrix Delivery Services Web Application(citrixfederationauthentication:authenticate:post:_citrix_authentication)\Controller Action Calls / second
Citrix Delivery Services Web Application(citrixfederationauthentication:authenticate:post:_citrix_authentication)\Controller Action Average Time (Microseconds)

Results:
(citrixfederationauthentication:authenticate:post:_citrix_authentication)\Controller Action Calls / second: 1
(citrixfederationauthentication:authenticate:post:_citrix_authentication)\Controller Action Average Time (Microseconds): 4,850


$stage = “Resource Enumeration”
$store + “Resources/List”

Response:

This call returns a list of all the resources for which you have access.  The counters important to this call are:
“Citrix Receiver for Web\List resources Average Time (microseconds)”
“Citrix Dazzle Resources Controller\List Whole Body Calls / second”
“Citrix Dazzle Resources Controller\List Whole Body Average Time (Microseconds)”
“Citrix Delivery Services Web Application(authservice:tokenservices:post:_citrix_authentication)\Controller Action Calls / second”
“Citrix Delivery Services Web Application(dazzleresources:list:get:_citrix_store)\Controller Action Calls / second”
“Citrix Delivery Services Web Application(authservice:tokenservices:post:_citrix_authentication)\Controller Action Average Time (Microseconds)”
“Citrix Delivery Services Web Application(dazzleresources:list:get:_citrix_store)\Controller Action Average Time (Microseconds)”
“Citrix Receiver for Web\List resources Calls / second”
“Citrix Xml Service Communication(10.10.10.11)\Network Traffic Calls / second”
“Citrix Xml Service Communication(10.10.10.11)\Network Traffic Average Time (Microseconds)”
“Citrix Xml Service Communication(10.10.10.12)\Network Traffic Calls / second”
“Citrix Xml Service Communication(10.10.10.12)\Network Traffic Average Time (Microseconds)”
“Citrix Xml Service Communication(10.10.10.13)\Network Traffic Calls / second”
“Citrix Xml Service Communication(10.10.10.13)\Network Traffic Average Time (Microseconds)”
“Citrix Xml Service Communication(10.10.10.14)\Network Traffic Calls / second”
“Citrix Xml Service Communication(10.10.10.14)\Network Traffic Average Time (Microseconds)”
“Citrix Xml Service Communication(xenapp5.bottheory.local)\Network Traffic Calls / second”
“Citrix Xml Service Communication(xenapp5.bottheory.local)\Network Traffic Average Time (Microseconds)”
“Citrix Xml Service Communication(xenapp65t.bottheory.local)\Network Traffic Calls / second”
“Citrix Xml Service Communication(xenapp65t.bottheory.local)\Network Traffic Average Time (Microseconds)”

We have lots of exciting things happening here.  We’re reaching back and querying the XML brokers, some kind of authentication occurs, etc.

The results of these counters were:

Citrix Receiver for Web\List resources Average Time (microseconds) : 249,172
Citrix Dazzle Resources Controller\List Whole Body Calls / second : 1
Citrix Dazzle Resources Controller\List Whole Body Average Time (Microseconds) : 182,206
(authservice:tokenservices:post:_citrix_authentication)\Controller Action Calls / second : 1
(dazzleresources:list:get:_citrix_store)\Controller Action Calls / second : 2
(authservice:tokenservices:post:_citrix_authentication)\Controller Action Average Time (Microseconds) : 4,549
(dazzleresources:list:get:_citrix_store)\Controller Action Average Time (Microseconds) : 8,391
Citrix Receiver for Web\List resources Calls / second : 1
Citrix Xml Service Communication(10.10.10.11)\Network Traffic Calls / second : 1
Citrix Xml Service Communication(10.10.10.11)\Network Traffic Average Time (Microseconds) : 0
Citrix Xml Service Communication(10.10.10.12)\Network Traffic Calls / second : 1
Citrix Xml Service Communication(10.10.10.12)\Network Traffic Average Time (Microseconds) : 36,820
Citrix Xml Service Communication(10.10.10.13)\Network Traffic Calls / second : 1
Citrix Xml Service Communication(10.10.10.13)\Network Traffic Average Time (Microseconds) : 37,622
Citrix Xml Service Communication(10.10.10.14)\Network Traffic Calls / second : 1
Citrix Xml Service Communication(10.10.10.14)\Network Traffic Average Time (Microseconds) : 43,121
Citrix Xml Service Communication(xenapp5.bottheory.local)\Network Traffic Calls / second : 1
Citrix Xml Service Communication(xenapp5.bottheory.local)\Network Traffic Average Time (Microseconds) : 95,575
Citrix Xml Service Communication(xenapp65t.bottheory.local)\Network Traffic Calls / second : 1
Citrix Xml Service Communication(xenapp65t.bottheory.local)\Network Traffic Average Time (Microseconds) : 149,888

With these counters we can see how long it took the brokers to respond.  My broker that has a few hundred applications took the longest, followed by a broker of an older farm with dozens of apps, then three where only a single app each is published from them.  I got a 0.0 for enumeration for one service.  I’m not sure what that’s about (maybe it exceeded enumeration timeout and is now excluded?).  Total time to list resources was 0.249 seconds.


$stage = “Get User Name”
$store + “Authentication/GetUserName”

Response:

This call simply returns your display name (or logon name if no display name is specified).

Two counters were hit:
“Citrix Delivery Services Web Application(authservice:tokenservices:post:_citrix_authentication)\Controller Action  Calls / second”
“Citrix Delivery Services Web Application(tokenvalidation:tokenvalidation:get:_citrix_authentication)\Controller Action Average Time (Microseconds)”
“Citrix Delivery Services Web Application(authservice:tokenservices:post:_citrix_authentication)\Controller Action Average Time (Microseconds)”

The results of these counters were:
(tokenvalidation:tokenvalidation:get:_citrix_authentication)\Controller Action  Calls / second : 2
(authservice:tokenservices:post:_citrix_authentication)\Controller Action  Calls / second : 1
(tokenvalidation:tokenvalidation:get:_citrix_authentication)\Controller Action Average Time (Microseconds) : 2,200
(authservice:tokenservices:post:_citrix_authentication)\Controller Action Average Time (Microseconds) : 4,551


$stage = “AllowSelfServiceAccountManagement”
$store + “ExplicitAuth/AllowSelfServiceAccountManagement”

Response:

This call appears to return True or False.

“Citrix Delivery Services Web Application(selfserviceaccountmanagement:allowselfserviceaccountmanagement:get:_citrix_authentication)\Controller Action  Calls / second”
“Citrix Delivery Services Web Application(selfserviceaccountmanagement:allowselfserviceaccountmanagement:get:_citrix_authentication)\Controller Action Average Time (Microseconds)”
“Citrix Delivery Services Web Application(authservice:tokenservices:post:_citrix_authentication)\Controller Action Average Time (Microseconds)”
“Citrix Delivery Services Web Application(authservice:tokenservices:post:_citrix_authentication)\Controller Action  Calls / second”

The results of these counters were:
(selfserviceaccountmanagement:allowselfserviceaccountmanagement:get:_citrix_authentication)\Controller Action  Calls / second : 2
(selfserviceaccountmanagement:allowselfserviceaccountmanagement:get:_citrix_authentication)\Controller Action Average Time (Microseconds) : 2,247
(authservice:tokenservices:post:_citrix_authentication)\Controller Action  Calls / second : 1
(authservice:tokenservices:post:_citrix_authentication)\Controller Action Average Time (Microseconds) : 6,014


 

$stage = “Download all the icons”
$store + $iconurl

Response:

<downloads all icon files>

This call hits the following counters:

“Citrix Receiver for Web\Get icon Average Time (Microseconds)”
“Citrix Receiver for Web\Get icon Calls / second”

The results of these counters were:

Citrix Receiver for Web\Get icon Average Time (Microseconds) : 285.351
Citrix Receiver for Web\Get icon Calls / second : 152.259


$stage = “ICA Launch.GetLaunchStatus”
$store + $appToLaunch.launchstatusurl

Response:

This call hits the following counters:

Citrix Receiver for Web\Get launch status Calls / second
Citrix Receiver for Web\Get launch status Average Time (Microseconds)
Citrix Delivery Services Web Application(dazzleresources:launchica:post:_citrix_store)\Controller Action Calls / second
Citrix Delivery Services Web Application(dazzleresources:launchica:post:_citrix_store)\Controller Action Average Time (Microseconds)
Citrix Xml Service Communication(10.10.10.11)\Network Traffic Calls / second
Citrix Xml Service Communication(10.10.10.11)\Network Traffic Average Time (Microseconds)

The results of these counters were:

Citrix Receiver for Web\Get launch status Calls / second : 1
Citrix Receiver for Web\Get launch status Average Time (Microseconds) : 152,721
Citrix Delivery Services Web Application(dazzleresources:launchica:post:_citrix_store)\Controller Action Calls / second : 1
Citrix Delivery Services Web Application(dazzleresources:launchica:post:_citrix_store)\Controller Action Average Time (Microseconds) : 5,091
Citrix Xml Service Communication(10.10.10.11)\Network Traffic Calls / second:  2
Citrix Xml Service Communication(10.10.10.11)\Network Traffic Average Time (Microseconds) : 65,709

Storefront will only fetch the status for the application from the broker that the application belongs.  If I run this query multiple times, hitting different brokers, the XML service communication populates more information.  The information here can be useful for you to find which broker is getting hit the most by looking at the “Network Traffic Calls / second” and you can find whether it’s overloaded by the “Network Traffic Average Time” being a number that grows as your load grows.  As with everything, it’s probably best to get some “base” numbers when load is low and then again when load is high to get your range.


$stage = “ICA Launch.LaunchIca”
$store + $appToLaunch.launchurl

Response:

We get an ICA file.  The performance counters that are important:

Citrix Delivery Services Web Application(dazzleresources:launchica:post:_citrix_store)\Controller Action Calls / second : 1
Citrix Delivery Services Web Application(dazzleresources:launchica:post:_citrix_store)\Controller Action Average Time (Microseconds) : 5,453
Citrix Receiver for Web\Get Ica file Calls / second : 1
Citrix Receiver for Web\Get Ica file Average Time (Microseconds) : 1,255,237
Citrix Xml Service Communication(10.10.10.14)\Network Traffic Calls / second : 2
Citrix Xml Service Communication(10.10.10.14)\Network Traffic Average Time (Microseconds) : 530,153

 


Final results:

Taking all the operations and the time it took, I sorted the list according to duration.

The following operations list the total duration of that specific task:

“Get Ica file”
“List resources”
“List Whole Body”
“Get launch status”
Excluding them shows us the sub-tasks that actually consumed the majority of the time spent:

The XML communications is what consumes the majority of the processing time.  The items starting in ‘brackets ()’ are the Citrix Storefront processing time that it spent.  Being in the single “thousands” of microseconds is super fast.  This essentially shows us that it takes next to no time at all for Storefront to execute the tasks that it needs.


Analysis:

Storefront has some great new performance counters that can help you determine your pain points.  Access to Citrix is usually talked about in terms of ‘rate’ so the per-second and average time counters are excellent in helping determine what is the component taking so long to do whatever task.  The breaking down of how long individual XML brokers take is a HUGE plus as you should be able to accurately gauge which Citrix FARM is now causing slowness in logon, enumeration or launching for your users.

Read More

Citrix Storefront – Performance and Tuning – Part 2 – PNA Traffic simulation

2017-05-30
/ /
in Blog
/

In part 1 I created a script to simulate users going through their web browser, logging in to Storefront, and launching an application.

In this post I’m going to simulate “PNA traffic”.  “PNA” is the icons delivered to your desktop or start menu via Citrix Receiver.

When connecting to Storefront or Web Interface the following can occur:

  1. This is your first connection and you need to download/cache the icons from the server
  2. This is a subsequent connection and you only need to validate you have all the icons
  3. You connect and PNA discovers you are missing an icon or have a new application assigned and proceeds to download any missing/different icons

All connections from PNA to Storefront/Web Interface start with “config.xml” .  From there, it queries for icons and downloads them.  This is what each of the 3 scenarios described look like:

 

The first time you connect via PNA

 

Subsequent connections after icons have been cached.

 

2 new applications published to the user

 

The first connection “config.xml” returns an xml file detailing the properties of the store.  Show icons on desktop/start menu? What are the URL’s for resource enumeration, reconnection, change password, etc.?  What logon methods are available?

All these questions and more are answered by the config.xml.

The second connection “enum.aspx” with a body size of 175 bytes is a POST request for the PRELAUNCH stage of PNA.  Are there any applications configured for PRELAUNCH?  POST request looks like this:

If you don’t have any applications configured for PRELAUNCH you receive a response like this:

The next enum.aspx request is a POST request that asks for all the icons:

And the response is a rather large one (1,758,490 bytes in my example) with application properties and details.  Part of the reason it’s so large is the icon data is stored as ASCII.  Here’s a small snippet of just 2 applications:

The subsequent POST request for icons (most roughly ~21,000 bytes in size) look like this:

With the response being:

Lastly, application launches over PNA are a POST request that look like this:

The content of that POST request looks like this:

And the response is a ICA file that Receiver executes.


With each of these requests we can see that PNA sends your username/password/domain to the server to get the relevant information.  This means we can script these requests using WCAT as the data being POST’ed is actually static.

Using the wcat scenario creator, download the WCATScenarioGenerator.dll and save it to: “C:\Program Files (x86)\Fiddler2\Scripts”

 

Open Fiddler.  Capture PNA operation by closing Citrix Receiver and reopening it.  Logon (if necessary) and launch an application.  If you want a more intensive logon, ensure your icon cache is cleared so that it forces new icons to be downloaded.  This will be the ‘scenario’ that we will be executing against.  Clean up any requests that don’t go to your web interface/storefront.  My Fiddler looks like this:

Select your items and in the black bar enter “wcat addtrans” and hit enter.

In the same bar enter “wcat save” and hit enter.

 

This will create a file called “fiddler.wcat” in your “C:\Program Files (x86)\Fiddler2” folder.

This file will actually require some cleanup as the WCAT scenario generator captures things literally and the scenario file requires escaping of double-quotes.

So in the wcat file, lines like this:

 

Need to be modified to look like this:

 

To execute our script, install wcat and launch the controller via the command line like so:

What each of these settings means:

-t = scenario file to use
-f = settings file to use (just using default)
-s = server to target
-p = port to connect
-c = clients that need to connect (this is the number of wcclient.exe’s that will connect to the controller)
-v = number of virtual clients that will connect
-w = warmup time (clients and virtual clients will connect in the amount they have / warmup time)
-u = duration for full load (all clients should be connected)
-n = cooldown, clients start disconnecting (opposite of warmup)

For my example, if I use my parameters for the controller then I need to start 10 clients be executing:

(Win7.bottheory.local is running the controller).

This command can be executed 10 times on the same box, even the same one as the controller, or on some random combination of 1-10 different boxes as long as you match the number of “clients” to the controller “client” excepted number of connections.


Lastly, here is a powershell script to measure the performance of each action of the PNA request.  You will need to modify it for your domain/(webinterface/storefront URL)/username/password.  This script will measure the amount of time each stage takes and the total, overall time and saves it as a CSV.

Here’s an example of the CSV output:

Some example commands:

Examples of “stress component” output:

And the script:

 

 

Read More

Citrix Storefront – Performance Testing and Tuning – Part 1

2017-05-24
/ /
in Blog
/

I’ve used the Web Capacity Analysis Tool (WCAT) in the past to measure the performance of Citrix Web Interface with some success.  So I thought this tool would be perfect for load testing Storefront.  I loaded up Fiddler, set up the WCAT extension, captured a web logon and then application launch.  The whole process looked like this:

Pretty simple right?

I logged on with Domain Passthrough authentication, I clicked on an application and I was done.  I have my customizations added in as well.  But what is actually happening?  How long does each step of the actual process take?  To determine this answer, we go to Fiddler to capture our flow so we can examine each step.

I truncated all the icon resource calling.  You can see it calls around 120 individual icon URLs.  I have my two custom ‘helpers’ (ADInfo and LogonType) that determine logon preference and whether we should get workspace control enabled or disabled (LogonType.aspx and GroupMembership.aspx).

So the actual calls to Storefront revolve around 7 unique queries to the Storefront server.  They are:

Fortunately, Citrix has documented how these need to be configured to successfully call these services.

With all this setup, I took my scenario file and executed it.  Nothing appeared to happen.  I broke down the scenario file into the individual calls and found where it was breaking.  This Citrix documentation explains it nicely:

Cross-site request forgery token

To protect against cross-site request forgery (CSRF) attacks, the Web Proxy APIs require that a CSRF token be supplied by the client, unless specified otherwise. This is a random string generated by the Web Proxy for the duration of the session and communicated to the client using a session cookie. Clients must read the value of this cookie and send it back to the Web Proxy in most API calls, as either the value of a header named Csrf-Token (note the hyphen) for POST requests, or as the value of a query string parameter named CsrfToken for GET requests.

 

The part in bold and underlined, is troublesome with WCAT.  WCAT does not appear to have this ability (read the value of a cookie and set a header to send it back to the web proxy).  What Storefront does, is send back a set-cookie back to the client which WCAT has no problem with…  but the data Storefront sends back is multiple values within that set-cookie command.  And this is a problem.

This is supposed to take this ‘Set-Cookie’ command and set two different values:

Cookie Value
CsrfToken FE2148E03989CB263CCD82A5888BF039
path /Citrix/StoreWeb/

But what WCAT does is create a single cookie that looks like this:

Cookie Value
cookie CsrfToken=FE2148E03989CB263CCD82A5888BF039; path=/Citrix/StoreWeb/;

WCAT creates a cookie with the entirety of a string value instead of separating them out.  Is there a way to parse this Set-Cookie command so that these are stored correctly?

Unfortunately, I was not able to find a way to do this with WCAT.

However, we can use Powershell to accomplish this job.  Ryan Butler has created a script to query the Storefront services to generate an ICA file.  This script is about 90% of what I need, however I’m not interested in doing an explicit logon, I want to do Domain Passthrough (integrateWindows) authentication, and I want to simulate the process as was captured by Fiddler, so I’ll be calling the additional services (GetUserName, AllowSelfServiceAccountManagement, etc.) and capture the time required for each section.

My Storefront Logon/Stress testing script:

 

And this is the output:

 

We can now run this script concurrently to simulate multiple clients.  Or we could run it with a command like so:

To stress an individual component.  By stressing the individual component we can actually determine which process on the Storefront server deals with which service.  So which components equals which service?

Get Auth Methods:

This component stresses “Citrix Receiver for Web”


Domain Pass-Through and Smart Card Authentication:

This component stresses “Citrix Receiver for Web” and “Citrix Delivery Services Authentication”


Resource Enumeration:

This component stresses “Citrix Receiver for Web” and “Citrix Delivery Services Resources”


Get User Name:

This component stresses “Citrix Receiver for Web”


AllowSelfServiceAccountManagement:

This component stresses “Citrix Receiver for Web” and “Citrix Delivery Services Authentication”


“GetLaunchStatus”

This component stresses “Citrix Delivery Services Resources”


LaunchIca

This component stresses “Citrix Delivery Services Resources”


Now that we have this script and we can see the where individual components cause stress, we can begin to push our Storefront server to find its limits and how the different configurations are impacted.  I’ll write up my findings on the limits of Storefront next.

Read More

Citrix Storefront – Adventures in customization – Query group membership from aspx

2017-05-15
/ /
in Blog
/

I’ve written a script that can tie into your environment for Storefront or other web service.  This is preferable over the powershell HTTP listener (IMHO) because it can just run on the IIS server and doesn’t need to rely on any external program/service.  It’s a simple script to pull out whether a user is a part of a group or not.  However, it does require impersonation to be able query Active Directory if your environment does not allow anonymous queries (I believe most do not).  Impersonation will make the request come from the machine account, which typically does have authorization to query AD.

In order to set this up, I’ve created a web application in IIS with impersonation set.

NOTE: this was run on a Server 2016 box.  If your System.DirectoryServices assembly has a different version and public key you will need to update this script with that information.

This script does the following: “Create application pool”


 

“Add Web App”

And the “appcmd set config” creates our web.config file:

And the GroupMembership.aspx file:

To call the file, it’s the %hostname%\ADInfo\GroupMembership.aspx?DisplayName=%username%

For example:

 

And then we just modify our script.js to point to this URL instead:

 

Read More

Citrix Storefront – Adventures in customization – Dynamically configure features based on group membership

2017-05-11
/ /
in Blog
/

As per my previous posts, dynamically configure Workspace Control and Authentication based on group membership, this post will put them all together and provide a little GUI love to enable showing your options.  These two features need to be enabled and configured at different times.  The authentication choice needs to be in place before you logon.  Workspace Control is configured upon logon.

In order to ‘cheat’, authentication actually uses Windows authentication from your browser to the server-side script.  This way we can get your account and query your authentication feature group membership.  This won’t work with non-domain machines or browsers that don’t support Windows authentication (Safari?).  But this is OK.  For those caveats, we just redirect those users to the explicit logon page anyways, since their user account won’t be domain-aware.

If you get explicit logon, and then log in, we query the users entitlements for Workspace Control and configure accordingly.  This allows a much more dynamic method than the authentication feature.  By doing Workspace Control configuration after logon we can configure the settings to whichever user you use to logon.  So if my account is Explicit Logon, Workspace Control Disabled that’s what I get after the Storefront logon screen.  However, if I logon with one of my test accounts that has Workspace Control Enabled then it’s enabled when I hit the app list.  Even though my local user account and my Storefront logon are different I’ll get the features of the user that logged in to Storefront.  I think that’s pretty damn neat.

Ok, so let’s get to my finished product.

I edited the custom\style.css file and added the following:

And my completed ‘custom\script.js‘ file:

You’ll need to refer to my previous two posts for the Powershell HTTP LDAP listener and the Group-Membership.aspx file.

What does this look like for an end result?

 

And if you are a member of the various combinations of groups?

 

I have to admit, this was a LOT easier than I thought it would be.  Storefront is really powerful and easy to use.  My biggest complaint is the documentation is lacking on how to use the API’s but searching the Citrix support forums proved very fruitful (especially for how to use the authentication methods) for examples.  Hopefully these blog articles will help someone else and further demonstrate the power, flexibility and extensibility of the Citrix Storefront product.

Read More

Citrix Storefront – Adventures in customization – Dynamically configure authentication based on group membership

2017-05-10
/ /
in Blog
/

Continuing on from my previous post, in XenApp 6.5 and Web Interface we created 2 sites, one with explicit logon (user name and password) set as the authentication method and one set with domain passthrough.  What was configured was an AD group, “ExplicitLogon”, and then Windows Authentication was configured on the IIS sites.  When the user connected to the site, if they were a member of the domain, it would go to a custom aspx script that detected whether the user was a member of ‘ExplicitLogon’ or not.  If they were not a member they went directly to the domain passthrough site.  If they were a member, they would go to the explicit logon site and be prompted again for credentials.  Why is this configuration useful?  Two reasons…

  1. Allows lower level AD accounts to get an opportunity to logon to Citrix with accounts that have elevated permissions.  If your organization enforces ‘non-admin’ accounts for your local computers, then being a part of ExplicitLogon will direct you to the site where you can logon with an elevated account.
  2. Shared accounts that are not allowed access to Citrix applications.  If a shared account is detected as a member of ExplicitLogon it will give the real user a logon prompt where they can logon with their own credentials.

This configuration has served us fairly well for the last few years, but it has a couple drawbacks.

  1. Non-domain joined machines get the ugly ‘prompt’ to enter some form of credentials so the group check can be executed where they will have to enter credentials again (if a member of ExplicitLogon).
  2. Non-domain joined machine may get an error after entering credentials in the initial prompt (if they are NOT a member of ExplicitLogon).  The reason for this, that I can determine (and happens with non-domain joined Macintosh computers), is the browser will pass those AD credentials to the initial group membership check script but not to the next level — the domain passthrough check.

Can we solve the drawbacks with Storefront?

My thoughts are a new workflow that works like this:

1 – Attempt to query group membership with the browser’s “user” first
2- If we’re unable to to find group membership -> proceed to ExplicitLogon page
3 – If we retrieve group membership -> check for ExplicitLogon group
4 – if ‘ExplicitLogon’ group == true -> proceed to ExplicitLogon page
5 – if ‘ExplicitLogon’ group == false -> proceed with domain passthrough

This is the logical structure:

 

 

Can I make this happen?  To start I created a store with both ExplicitLogon (User name and password) and Domain pass-through authentication methods enabled.

The server side script to check group membership:

And the technical flow:

And this is what the custom/script.js looks like when we convert the flow to reality:

 

The results?

User: TEST1

User: TEST2

 

It works perfectly!  We can now define users to utilize ExplicitLogon via a user group.  And if they are not a member of that user group it will do pass-through authentication.  And even further to that, if they are NOT a member of the domain it will automatically redirect them to the Explicit Logon page!

Read More

Citrix Storefront – Adventures in customization – Restrict app visibility with single factor authentication, show all apps with two-factor authentication

2017-05-09
/ /
in Blog
/

I have been working with a colleague of mine (Saman Salehian) who has been working on a project with a Citrix Netscaler.  One of the hopes of this project is to offer Citrix applications externally.  A problem was posed to me about restricting users to only access non-critical, non-patient facing applications (eg, Outlook, intranet site, etc.) if they logged in with their domain credentials, but if users were using a two factor authentication method to show all applications.

Citrix has 3 articles (one, two three) that I’ve been able to find about executing on this.  The problem with these articles is that they are now outdated.  Citrix has a much more flexible and (In My Humble Opinion) better way to hide/show applications.  And that is through the Receiver Extension APIs.  Through a single store, I’ll be able to show and hide applications dynamically.

The two API calls that are relevant are:

excludeApp(app)
Exclude an application completely from all UI, even if it would normally be included.

includeApp(app)
Include an application, even if it would normally be excluded. For example a platform might exclude applications intended for a different platform.

The architecture of this solution looks like this:

 

It’s pretty damn simple.  Look that a specific cookie has a specific value and if it does NOT have that value, exclude the app(s) from being shown.

So the role of the Netscaler here is when the user logs on, it will write a cookie based on the authentication.  Our Storefront script will check for the value of that cookie.  If the cookie contains our known value then we iterate through all applications and look for some unique text we’ve set in the application description field (this works with both XenApp 6.5 and 7.X) and hide those applications.  For my example, I’ve added ” 2FA” to the application description field for the applications I want excluded from single-factor authentication. Note: I’ve required a ‘space’ before the characters 2FA.