Office 365 – HIPAA in 3 easy steps

Like all compliance policies, the Health Insurance Portability and Accountability Act (HIPAA) is not without its twists and turns.  The act itself details out the handling of patient health and identifying data (PHI and PII) (the cliff notes are here), but what does all of this mean for the Office 365 suite?

Office 365 in general contains the tools to meet the technical safeguards for HIPAA compliance.  Unfortunately out of the box it will absolutely not meet the safeguards, but thankfully a few minutes is all it takes to bring the suite up to snuff.

Continue reading Office 365 – HIPAA in 3 easy steps

ADFS Claims Rules Sample # 2 – Enforce Multifactor Authentication

The ADFS GUI allows for some rudimentary control of multifactor authentication (MFA).  This control centers around Device Trusted/Untrusted, Network Inside/Outside, and User Group Members.  But what if you wanted an exception group, or possibly only on the passive endpoint, not the active endpoint, of if you wanted to lock down MFA to only specific apps?  You can not do that through the GUI.  You need Powershell.

Multifactor authentication rules are set on the AdditionalAuthenticationRules parameter when running the command-let Get-AdfsRelyingPartyTrust.  In my previous post, I outlined how to control Office 365 via policies.  The same goes for here, where you can use any combination of claims rules to control the behavior of MFA.

Please note you do need the MFA provider configured on ADFS.  ADFS claims rules can not differentiate between providers if more than one is selected.

Step 1:  You need to focus these claims rules on a particular trust.  You can do it global as well, but for this example we are going to focus again on Office 365.  Run the command-let:

 Get-AdfsRelyingPartyTrust - Name "Microsoft Office 365 Identity Platform"

You will see that parameter –AdditionalAuthenticationRules  is empty.

Step 2:  Determine the claims you want to invoke MFA.  In this sample, I want to target the passive endpoints for all external users, that do not belong to a specific Active Directory group.  Remember that the AD group is via SID, not name.

exists([Type == ""]) && exists([Type == "", Value =~ "(/adfs/ls)|(/adfs/oauth2)"]) && Not exists([Type == "", Value =~ "S-1-5-21-0000000000-000000000-0000000000-000000"]) => issue(Type = "", Value = "");

Step 3:  Pulling it all together.  We want to insert this claim into  –AdditionalAuthenticationRules for Office 365.  To do this, run the following powershell:

$rp = Get-AdfsRelyingPartyTrust –Name "Microsoft Office 365 Identity Platform"
Set-AdfsRelyingPartyTrust –TargetRelyingParty $rp –AdditionalAuthenticationRules ‘exists([Type == ""]) && exists([Type == "", Value =~ "(/adfs/ls)|(/adfs/oauth2)"]) && Not exists([Type == "", Value =~ "S-1-5-21-1338325200-504760778-2079600828-465239"]) => issue(Type = "", Value = "");’

And there you go.  Now if you ever need to remove the rule, just blank it out:

$rp = Get-AdfsRelyingPartyTrust –Name "Microsoft Office 365 Identity Platform"
Set-AdfsRelyingPartyTrust –TargetRelyingParty $rp –AdditionalAuthenticationRules ‘’

That will remove the MFA authentication.

Open letter to “the business”

To those who request IT provided services for your initiatives:

It is the job of a technology professional to ensure the success of your project, but at the same time uphold the policies of the organization.  This can lead to frustrations on both sides of the aisle.  Completely understandable, but it is not a requirement for IT to block innovation and cause delays.  Quite the opposite in fact.  IT is a center for fostering and embracing innovation.

On Business Requirements:

Let us do our jobs as we do to you.  We are here to serve you.  Give us your complete business requirements in laymen’s terms.  Help us understand your processes and your ideas, and we will provide an answer that marries your requirements to a technical solution.  We do not need a technical solution from you up front, nor do we need constantly changing requirements.  This will only lead to further questions, delays, and frustrations.  We are a partner to you, and want to be part of your success.


On Tech-know-how:

Trust us in our solutions.  We may throw around acronyms such as SFTP, DMZ, IOPS, SMB.  If you do not understand it just ask, but be sure that we will always match up to your requirements.  We may not understand all of your acronyms, and never try to be the professional you are, but rest assured as a partner what we provide will bring upon your success.


On Shadow IT:

Shadow IT is the notion that you will go out and purchase your own solutions to try to bypass our processes.  We are not afraid of it, but be careful if you pursue this avenue as you may be doing more than just bypassing IT. You may be breaking business policies.  If you include us in your shadow IT initiatives we can help make it even more successful, because we understand service integrations, security policy, and can make sure you are meeting your requirements.  Remember, we are partners, not enemies.


Aligning and understanding efforts across all departments creates a cohesive business strategy.  We are here to drive business innovation and provide services and resources to make that happen, while maintaining compliance and security.  We are partners in this journey and look forward to working with you.


The IT Professionals

ADFS Claims Rules Sample # 1 – Office 365

Microsoft has a nice tutorial on understanding and implementing claims rules for the Office 365 platform, however if you set the default rule to deny all (by removing the Permit All claims rule), there are a few additional rules that need to be configured based on what you are trying to do.  Please note that as conditional access policies mature, some of these rules can instead be accomplished in Azure AD.

Sample Rules for Office 365.

Permit OWA and other Passive Claim Access

This rule allows all passive claims (anything accessing the /adfs/ls URL) to ADFS.

exists([Type == "", Value =~ "(/adfs/ls)|(/adfs/oauth2)"])
=> issue(Type = "", Value = "true");


Permit Active Sync

Users accessing the active endpoint of ADFS with the client names of Auto Discover or ActiveSync are allowed to authenticate.

exists([Type == "", Value == "/adfs/services/trust/2005/usernamemixed"])
&& exists([Type == "", Value =~ "Microsoft.Exchange.ActiveSync|Microsoft.Exchange.Autodiscover"])
=> issue(Type = "", Value = "true");


Permit Outlook (No Modern Authentication).

This rule is for legacy access of the Outlook client.  It connects to the active endpoint of ADFS, and access can be restricted based on client IP range (public address).  In this example, there is a reference to a single external IP address, as well as a reference to a /24 Class C address range.

exists([Type == "", Value == "/adfs/services/trust/2005/usernamemixed"])
&& NOT exists([Type == "", Value =~ "Microsoft.Exchange.ActiveSync|Microsoft.Exchange.Autodiscover"])
&& exists([Type == "", Value =~ "\b192\.168\.1\.1\b||\b192\.168\.10\.([0-9]|[1-9][0-9]|1([0-9][0-9])|2([0-4][0-9]|5[0-5]))\b"])
=> issue(Type = "", Value = "true");


Additional Rules that you may require.

By limiting access to the endpoints of ADFS, you will inadvertently break access to other Office 365 applications.  Here are three that I have come across in my testing.

Allow the Office Suite, as well as SharePoint Designer

This rule will allow connections from Word, Excel, etc. to connect to Office 365

exists([Type == "", Value =~ "/adfs/services/trust/2005/usernamemixed|/adfs/services/trust/2005/windowstransport"])
=> issue(Type = "", Value = "true");

Allow Azure AD Join

This rule will reinstate the ability for Azure AD join of Windows 10 devices.

exists([Type == "", Value == "/adfs/services/trust/13/usernamemixed"])
&& exists([Type == "", Value =~ "Windows-AzureAD-Authentication-Provider"])
=> issue(Type = "", Value = "true");


Catch all rule for the Active Endpoint

This rule will allow all access to the active endpoint of ADFS.  This will allow PowerShell access to the Office 365 tenant.  In this sample, I am locking down this access based on group membership (SID value of the group).

exists([Type == "", Value =~ "/adfs/services/trust/2005/usernamemixed|/adfs/services/trust/2005/windowstransport"])
&& exists([Type == "", Value =~ "S-1-5-21-1000000000-500000000-2000000000-540000"])
=> issue(Type = "", Value = "true");

30 Seconds with the NComputing RX-HDX

RX-HDX Hardware (image care of  Product Website:

End point strategy is always a hot topic at any future planning meeting.  In my world, finding the right balance of usability, manageability, and cost wrapped in a thin client is a tricky endeavor, especially given the fact that my enterprise computing environment is Microsoft Windows centric, with Citrix XenApp as the application delivery method.


When I had the opportunity to check out the NComputing RX-HDX Raspberry PI based appliance I jumped at the chance.  Small, HDX supported, user friendly with centralized management, what’s not to love

NComputing’s motto is Compute Smartly.  I love that.

Opening the box I found basically a secured Raspberry Pi and power adaptor.  The system itself is booted off of a SD Card, but that port is blocked off.  Stupid me, I forgot to order an HDMI to VGA adaptor, as the monitor I had to test does not contain an HDMI port.

A couple of days later after my Amazon order came in I was up and running.  The initial setup which is menu driven (and if you set up the optional centralized management console is centrally deployed).  Simple to use with a bunch of options.  The operating system (NoTouch OS) mimics Windows, and the look and feel is well done.  The help wiki is also very helpful and found at

  • Con:  The Citrix Receiver is the ugly Linux Receiver, not the much prettier Storefront based Receivers.  This is purely cosmetic, but when shifting from the Windows or macOS version to this there could be user complaints.  An alternative though is to configure the built in Firefox browser to go to the Storefront instead, but in order for advanced functions to work you do need to set Firefox to root.  Not the best option for security.
  • Con:  Printing to a Windows Print Server DOESN’T WORK as advertised.  In fact it barely works, and there is little to no feedback when configuring printing.  Plugging in a USB printer works fine.
  • Pro:  Thin Print support.  This is a really nice feature and can negate the Windows Print Server issue.
  • Pro:  Reboot at user session logoff and other security controls.  Security is a focus point, and the ability to clear all browser cache at logoff, and when a session window is closed automatically reboot the device for a fresh session is a great feature.
  • Pro: Imprivata Support.  Built in SSO support to Active Directory.  Perfect.
  • Pro:  Dual monitor support.  Critical in healthcare and financials.  Its a shame though that its a separate cost option.

Price:  Not expensive at approx. $150 dollars.  Support is annual though and a separate item.  This does not include any Microsoft client access licenses, which are required for RDS and XenApp connections.

Verdict:  Fix the printing and upgrade the Receiver, and you have a really nice product that is enterprise ready.



Continue reading 30 Seconds with the NComputing RX-HDX

IT Phrase of the Week: Five Year Old Soccer Strategy

One of my favorite phrases I hear all of the time.  In a cloud centric world where making sound decisions is key, one must always remember to not just chase the ball.  We need to think strategically, logically, head in a common direction and achieve a common goal that is good for the enterprise as a whole, not just the individual.

Citrix Issue RESOLVED: Netscaler Gateway white screens after login/Missing or broken icons on clientless access.

In a recent project I was heavily involved in and lead the design of, the end state was the use of the Netscaler Unified Gateway to provide access capabilities to enterprise resources. Unbeknownst to myself, my team, and my Citrix consulting partners an issue was uncovered that brought the Netscaler platform to its knees.

The Symptoms

There are three primary use cases for the Unified Gateway platform that this design covered.  The first, VPN using the web interface of the Gateway, not through the gateway plugin.  The second, clientless VPN using bookmarks.  Lastly, Citrix Storefront, delivered through the clientless VPN web interface.  The Netscaler itself (version 11.1.57.x for this architecture) is shipped with a stock configuration that is not suitable for peak loads on the platform for example at the start of a work shift.  During these login storms, the Netscaler itself would run out of processes, causing the users to experience white screens, missing clientless VPN bookmarks, and session hanging.  Over a period of minutes the appliance would eventually crash.

The Issue

Netscaler firmware is a version of FreeBSD with an integrated version of Apache web server.  When using a custom theme on your gateway, all user traffic bypasses cache and hits the Apache server directly.  The Apache configuration is pretty stock, with HTTPD.CONF (location /etc/httpd.conf) consisting of the following values:

minspareservers: 1 

maxspareservers: 10 

StartServers: 5 

timeout: 120 

maxrequestserchild: 10000 

keepalivetimeout:  15 seconds 

maxclients: 30

What this means is that at startup, the Netscaler will start 5 processes of Apache, have a max of 30 processes, and keep anywhere between 1 to 10 processes spare and in a waiting state.  It will hold processes waiting for 15 seconds before moving on in the queue, with an overall timeout after 120 seconds between receives and sends.  Each process has a max request queue of 10000.

While observing the behavior of the Netscaler while the clients are having issues, I was seeing the process counts jump to the max (30), causing system instability as the appliance was trying to keep up with user demand.  At 2000 connections, with appliance theoretical limit at 10000 connections, the whole system would go down.

CLI Command for displaying apache processes: ps -aux | grep httpd -wc

The Misconception

One may ask oneself, should I just buy a bigger appliance?  What about upgrading to Netscaler 12?  The answer is no and no.  While a bigger appliance would handle more Gateway connections, the Apache web server and the amount of RAM dedicated to Apache is the same regardless of which model you have.  Netscaler 11 and 12 both use the same Apache configuration as well, so firmware version is does not matter.

The Initial Citrix “Fix”

While working with Citrix support, the recommended course of action was to increase the maxclients to 50, as this would give the Netscaler a higher process ceiling.  The end result of this was causing the appliance itself to run out of memory trying to manage 50 processes at the same time.

The second recommendation was to scale horizontally to accommodate the logins.  Why would I scale horizontally when I have a box with a theoretically limit of 10000 connections, to handle 2000 to 3000 burst logins.

The Real Fix

The actual fix to this issue was a collaborative effort between myself and my teams, and Citrix consulting services.  Each bringing a different piece to the puzzle:

My Contribution: Optimize Apache.

The stock configuration is a subpar configuration that does not mirror reality.  While it works fine in isolated use cases, when all of the bells and whistles are activated it can not keep up with demand.  Here are the values of the new Apache configuration:

minspareservers: 5 

maxspareservers: 10 

StartServers: 5 

timeout: 100 

maxrequestserchild: 1000 

keepalivetimeout:  5 seconds

maxclients: 50

While still starting the appliance with 5 processes, the spares are instead kept between 5 and 10 processes.  This will allow the appliance to focus on the requests, instead of focusing on starting up processes.  By decreasing the max requests to 1000, if there are issues with the process it will not wait for a request queue of 10000 to recycle, and instead recycle much sooner.  The processes themselves are also only waiting 5 seconds between clients before moving on to the next in queue, instead of the stock 15.  I kept the 50 maxclients in good faith for Citrix stock configuration, but due to the optimizations the queue cycles too fast to ever hit that limit.

Citrix Contribution:  Enable Integrated Caching

Citrix consulting recommended to include integrated caching in the mix as well.  Citrix engineering stated that the integrated caching piece will not help with the login storms, as custom themes can not and will not cache by design.  Where it will help is once in, bookmark and resource requests can be cached, taking load off of the Apache web server.

set cache contentGroup loginstaticobjects -memlimit 768 

 set cache contentGroup OcvpnLoginstaticobjects -memlimit 768 

 save config 

 add cache selector en_config_xml_cache_selector   http.req.url.path   http.req.method   http.req.hostname 

 add cache contentGroup en_config_xml_cache_group -relExpiry 120 -maxResSize 16000 -memLimit 28 -hitSelector  en_config_xml_cache_selector 

 add cache policy en_config_xml_cache_pol -rule "HTTP.REQ.URL.PATH_AND_QUERY.STARTSWITH_ANY(\"vpn_cache_dirs\") && (HTTP.REQ.URL.CONTAINS(\"/resources/config.xml\") || HTTP.REQ.URL.CONTAINS(\"/resources/en.xml\"))" -action CACHE -storeInGroup en_config_xml_cache_group 

 bind vpn vserver VSERVER -policy en_config_xml_cache_pol -priority 5 -gotoPriorityExpression END -type REQUEST 

save config


The Aftermath

Success!  Not only did the issue go away, but I still haven’t been able to find the limits to this.  Thread counts hover around 30 at peak logins, when before they were at 50 before crashing the appliance.  I will say that this collaborative effort between myself and my team, and Citrix company in general (one fantastic consultant in particular) has been very successful.  This issue has been made known, and I am hopeful that a knowledge base article will be the next step, with eventual incorporation into the stock configuration.  Until then if you come across this issue, don’t scale out, just fix the problem.