Imprivata Password Reset Troubleshooting

One commonly overlooked but absolutely critical piece of an Imprivata implementation is the ability to reset active directory passwords, expired or otherwise. It’s one of those things that tends to fade into the background in the midst of other pursuits and resolutions, but if it isn’t accounted for, it can cripple an entire environment. As soon as users’ passwords start expiring, and they are told they need to reset them before they can login, an incomplete or incorrect configuration on the appliance can result in users getting completely locked out of their desktops, relegating them to downtime procedures or worse.

There are a few different stars that need to align for the Imprivata password reset to work seamlessly. None of them are particularly hard to address if you know what you should be looking at:

  • You may need to enable SSL. Navigate to the Users, Computers and Domains tab in the OneSign administrator console, then to the OneSign domains subtab, and select your domain. Ensure the “Use Secure Connection (SSL)?” checkbox is ticked. If it is not, tick it off and hit save. Imprivata will seek out the certificate, ask you whether you want to trust it, and once you answer affirmatively, SSL will be enabled. If instead you are met with an error indicating the connection fails after enabling SSL, you may need to upload the certificate yourself. This could possibly be happening because your certificate authority is not on the domain controller with which Imprivata is communicating. If that is the case, please reference this article for more information on generating the certificate, or this one about configuring LDAPS on your domain controller.
  • Also on the Users, Computers, and Domains > OneSign Domains > [Your domain] page, you will have an Administrator User Name and Password. Confirm that the user listed has sufficient rights to reset passwords across the domain and be sure that its password is not set to expire at any point. If this account’s password has expired, it will be unable to perform the necessary functions. Imprivata recommends this account be a domain admin, but account operator status will suffice. You could get away with password reset/account unlock rights alone, but if you are having problems with limited privileges, promote it to domain admin and see if your problem is fixed. Furthermore…
  • …Note that if you make the account anything less than a domain admin, the account will be unable to reset the passwords of other domain admins. This is per active directory, not a limitation of Imprivata itself.

If you have addressed all of the above and are still having problems, try accessing the domain controller itself as the Administrator account referenced in the second point. Attempt from there to reset a user’s password manually, without ever involving Imprivata to confirm it is not an issue with the account itself. I have heard rumors of people having to create a new account for no apparent reason, but if you find that it cannot change passwords from there, it certainly won’t work from the other side. Conversely, if it does work from there and still doesn’t work from the endpoints, you may want to confirm that your problem isn’t something a little more fundamental, like whether or not your machine is on the domain in the first place.

Imprivata Credential Passthrough with Citrix

When using Imprivata with XenDesktop or VDI-In-A-Box, you may find that connecting to a session results in your arriving at the Windows user login screen instead of a desktop. In order for the Imprivata credential passthrough to work in these environments, you need to install the agent via the command line with the following switch:

INSTALL_ONESIGN_NETPROV=TRUE

This will let Imprivata act as a Network Provider (it will appear in the ProviderOrder settings) and will allow for seamless credential passthrough from a Citrix Receiver or RDP client into an SSO-enabled desktop.

AppSense: Dynamic Idle Session Timeout with Environment Manager

If you are deploying a virtual desktop environment in a hospital setting, you can be absolutely assured that a user will, at some point, walk away from a computer and leave a session unlocked.

Without application-level single sign-on, this is a big security hole. With application-level single sign-on, it is a security nightmare, and I don’t doubt that it would constitute a smorgasbord of HIPAA violations. I imagine this is a problem that exists in other arenas as well, but alas, my scope of experience is as-yet limited.

In my last post, I gave an explanation of how to use Imprivata fade-to-lock from within the VDI using computer policy (albeit couched within an explanation of a workaround specific to Xenith 2 devices). Again, this is perfectly effective, and if it suits your needs, this article will bore you. That aside, if you are using a PC-based environment with Imprivata, this article will bore you even more. That is, the workaround here described is rendered moot when you have endpoints that accept their own computer policies.

However, if you are not using Imprivata, or you are using it with zero clients that do not allow for fade-to-lock, this may interest you.

For example, let’s say you have a few PCs in a publicly accessible room where random people wander in and out from time to time. It might behoove you to have an idle session timeout in this area set for one minute. This will combat the possibility of an outsider gaining access to the network or protected information.

Maybe you have another area that is behind locked doors and used only by employees with ID. You don’t want these people complaining that their computers keep locking whenever they glance down at their cell phones to read a text message, so you might want an idle session timeout of 10 or more minutes. So how do we stay secure and keep everyone happy?

Using a combination of AppSense and the Windows screensaver, we can meet both of their needs. As with many of the things I discuss, this presumes a device naming scheme that indicates the physical location of a device. It also presumes your ability to use that computer name as a condition within AppSense. If needed, you can refer to this post of mine for how that can be accomplished.

Did you know you can set any program you want to be a screensaver? You may be able to intuit the remaining steps yourself if I explain that we are going to set up a session disconnect command as a screensaver. From there, it’s simply a matter of updating the time before screensaver activation as a user roams. In the interest of a full walkthrough, though:

  1. Before we begin, you will need to know the disconnect command appropriate for your environment. If you are using View, you are going to be using a tsdiscon command as your screensaver. If you are using Citrix XenDesktop, you will need a tool provided by Xirtica Software called QuickDisconnect (available here). In the latter case, the tool requires an installation on your master image. You’re going to need a recompose to make this work anyway, so hopefully that isn’t a huge concern.
  2. Once you have your method available, you will need to turn it into a usable screensaver. As I do not have a reliable webhost to host these files for you, nor the desire to create each variation at this time, I will simply explain: Either through the use of AutoHotkey (with its simple compiler) or otherwise, write a script that runs either tsdiscon in the case of View, or /PATH/TO/QD.exe /DISCONNECT in the case of XenDesktop.
  3. Then compile the script to an .exe, and simply change the .exe extension to .scr. That’s it for that.
  4. To install the screensaver, place it in the %systemroot%\system32 folder, right-click and choose “Install.” You can, at this point, recompose your pool. The rest will be handled by AppSense.
  5. In your environment manager config, create a new node, referred to herein as “Set Screensaver.”
  6. Create an action to set the “Force specific screensaver” ADMX policy. In case you didn’t guess, you want to force the screensaver you made in step 2.
  7. Also in this node, create a condition to check against the name of the endpoint computer and value it with a string to reflect the area that needs its own timeout. For example, if all machines in the unsecured public area of my earlier example are WAITINGROOM-01 through “WAITINGROOM-10, “If computer name contains WAITINGROOM” will be one of your conditions. Create as many more of these as you need to cover all the areas requiring their own timeout settings.
  8. For each condition, create a Set Registry Value action that sets a reg_sz value for HKCU\Software\Policies\Microsoft\Windows\Control Panel\Desktop\ScreenSaveTimeout to be the number of seconds until the session disconnects. For example, set the string to 60 if you want the timeout to be one minute. Set this value accordingly for each of the conditions you created in step 6.
  9. Trigger your “Set Screensaver” node at both login and at session reconnected/session unlocked.

And voila! As users roam about your premises, AppSense will check what computer they are accessing from and, based upon that device’s name, will change the Windows screensaver timeout period. You now have dynamic idle session timeout!

Once the screensaver is activated using Windows’ internal idle activity monitor, Windows will indiscriminately run a command that just so happens to disconnect their session. As a final word of warning: Windows has a preview of the screensaver built into the “Set Screensaver” section of the control panel. Accessing it after the steps above will “preview” your disconnect command, which will look remarkably similar to actually disconnecting your session. Don’t be alarmed–it just means it’s working.

Imprivata and the Wyse Xenith 2

Five posts into this blog and I’ve already had to talk about the Xenith 2 twice. The reasons for this are several: the information is fresh in my mind; the device is newer and lacks extensive documentation on the Googles as yet; I’m trying to stay motivated to keep this little project going by writing often, and I ran into all kinds of problems with these things…

Anyway, in addition to the aforementioned virtual driver error there were a few “gotchas” (as I am told they are called in the biz), so I will keep the exposition short in an attempt to cover everything in a single, hopefully intelligible post.

Enrolling a Proximity Card: OneSign Could Not Authenticate You

This particular customer was rolling out all new active directory accounts for its users at the same time as Imprivata, and so all users were given a provisional password that was set to expire. When attempting to enroll credentials on their badges, we noticed it worked just fine from a PC: The user would tap his or her badge; be prompted to enroll it; supply a user name and the provisional password; get prompted to reset it; select a new one, and the badge was enrolled with their newly reset password.

However, when this same workflow was attempted from the Xenith 2, all other things equal, users were invariably met with the dreaded “OneSign could not authenticate you” error. I am sorry to say we never got an actual fix for this, but as workarounds are my custom, I can at least offer the following advice: Have users reset their expired passwords first, spin up their session, tap out and enroll their badge with the newly reset credentials. It is not ideal, and will add a couple of minutes per user to the enrollment process, but if restricting enrollment to PCs is not an option, perhaps that much is.

Account Self-Service: Security Questions

Wanted to put into certain terms that this protocol is not supported from a Xenith device. There is, as of this writing, nothing you can put into your xen.ini file that will allow users to answer Imprivata security questions to reset passwords/access desktops. While we’re on the subject…

Xen.ini Parameter for Imprivata Use

OneSignServer = yourserverhere

Not a “gotcha” as such, but I couldn’t find that information anywhere. I had to get this awesome configuration generator tool (Source: FreeWyseMonkeys) just to figure it out. Seems simple in retrospect, but just in case, there ya go.

Walk-Away Security: Fade to Lock / Inactivity Lockdown

This is by far the biggest one, so I saved it for last. In just about every hospital I have worked, users are notorious for leaving their work unlocked and unattended behind them. Whether they used generic signons in the past, or whether they didn’t use computers at all, they have a strong propensity to walk away from a computer without locking it first. When Imprivata and application SSO comes into play, this can be a security nightmare.

In a PC-based environment, where you have a local Imprivata agent running and automating the connection to the desktop, you are free to make as many computer policies using as many individual timeouts as you’d like, and if you’re using fade-to-lock, they will fade and lock when or if you want any of them to do so. If, however, you are planning on using that same fade-to-lock feature on a zero client that will be connecting to linked clones or other non-persistent virtual desktops, your options become significantly more limited. Because there is no locally installed agent to manage it on a machine-by-machine basis, you have to apply all your settings to the virtual desktops themselves.

Unfortunately, this means you need to commit to a single timeout period for everyone, as there is no way to dynamically update Imprivata policy on singular machines. This is not to say you cannot get a little more granular with the idle timeout period across the environment if you want to use something other than Imprivata to lock them down (I’ll come back to this in another post, probably), but if you plan on using the awesome fade-to-lock functionality, you will have a single computer policy for all your virtual desktops that handles it for you.

Here’s where it gets tricky.

Enabling the fade-to-lock functionality in the computer policy for your virtual desktop is hypothetically all you need to do. In reality, when you are connected to the desktop from a Xenith 2, you find that your timer hits 0, and the desktop just sits there without doing a thing. Anyone can come up, move the mouse, and it’s as though nothing ever happened. Whatever Imprivata is attempting to do to lock the desktop is failing. What this tells me is that we need to adjust the behavior so that whatever happens when that timer hits 0, it disconnects the virtual session. My The workaround I came up with is as follows:

  1. The first thing we need is the ability to disconnect a session using a command. If you had been using View, tsdiscon would have sufficed. As you are on a Xenith 2, I will presume you are using XenDesktop, and confirm (in case you didnt know for sure) that tsdiscon does not work with XenDesktop. There is an alternative, of course, but do note that this is not a portable .exe but a program that actually does require an installation. Download it from here and install it on your master image.
     
  2. There is also a registry setting required for this workaround, so you might as well set it while you’re here:
    HKLM\SOFTWARE\SSOProvider\ISXAgent\LockVirtualSessionWithHotkey  dword:00000001

     
  3. Create a procedure code extension object to be triggered when the computer is locked. It should read (unless you installed it to a different path):
    “C:\Program Files\Xirtica Software\QuickDisconnect\QD.exe” /DISCONNECT

     
  4. Enable this procedure code in your virtual desktops’ computer policy. Additionally, go to your “override user policy” tab and check the box next to Challenges. Set any hotkey you wnat (it really doesn’t matter–just don’t pick one that a user might use in real life) and set it to Lock Computer when it is pressed.

That’s it. The endgame is here is that the timer will count down to 0 and Imprivata will have the ability to lock the virtual desktop itself. When it does so, the procedure code will note the lock and trigger the command that disconnects the virtual session, resulting in a session still available for reconnection and a secure walk-away.

That’s also it for the oddities I noted on these devices. If you’ve got more, let me know.

AppSense: How to Use Roaming as a Node Trigger

AppSense’s Environment Manager has a trigger for almost every occasion. However, let’s say you have a series of actions that you only want to run when a person roams to a new location. You could just set these to run at reconnect/session unlocked, but that means those actions are going to run every single time you reconnect to a session, even if you’re doing it from the same machine you just locked moments earlier. In the case of mapping printers, it’s a ton of unnecessary work to do it if the printers aren’t going to change.

There is no “location change trigger” built into AppSense. However, by setting up some fairly simple logic, you can make one of your own. All it takes is a few environment variables and a condition check. Set these up correctly, and you’ll be able to enact a series of actions only when a user roams his or her virtual session from one machine to another. In the printer example, there is no need to un-map and re-map the same set of printers every time a user disconnects and reconnects from the same physical device. You can instead update their printers only when they move to another area that requires a new set.

Before I continue, I should preface this by saying that all of the below presupposes an endpoint naming scheme that reflects the physical location of the machines in question. If you don’t have one of these, you should really put the effort into establishing one. You will not be able to get the most out of AppSense until you do.

Essentially, we are going to need to set up two different environment variables, henceforth referred to as CurrentPC and PreviousPC.  The TL;DR version of this post can be summed up in saying that we will determine in AppSense which PC the user connected from last time, compare it against the machine they are connecting from this time, and then run our actions if they are not the same machine. Our “location change trigger” is less a trigger than a simple condition whose parameters we will determine ourselves.

Step #1:

To make the aforementioned comparison work at the very first login, you will need to establish the PreviousPC variable even when there technically wasn’t one. For this, you will need a node that runs under the Login trigger. Pick any of the ones you have already (if they exist), relocate a pre-existing node that currently runs elsewhere, or create a new one. The only important thing to remember is that these needs to run before anything else we establish below.

In this node, create an action that values the PreviousPC environment variable with NULL. Bear with me, it will make sense later if it doesn’t already.

Step #2:

Create a node called “Set CurrentPC variable.”  In this node, you will run either of two VBscripts, depending on your environment type.

If using VMware View, create a custom action containing this script (Slightly modified from the one found in this AppSense Bigot article):

‘ get Clientname

Const HKEY_CURRENT_USER = &H80000001

Set wmiLocator=CreateObject(“WbemScripting.SWbemLocator”)
Set wmiNameSpace = wmiLocator.ConnectServer(“.”, “rootdefault”)
Set objRegistry = wmiNameSpace.Get(“StdRegProv”)
sPath = “Volatile Environment”

lRC = objRegistry.GetStringValue(HKEY_CURRENT_USER, sPath, “ViewClient_Machine_Name”,sComputerName) ‘Query Registry for client name

‘set the environment variable

Set oShell = CreateObject(“WScript.Shell”)
Set oUserEnv = oshell.Environment(“USER”)
oUserEnv(“CurrentPC”) = sComputerName
wscript.quit(0)

If you are using Citrix XenDesktop, use this variation instead:

‘ get Clientname

Const HKEY_LOCAL_MACHINE = &H80000002

Set wmiLocator=CreateObject(“WbemScripting.SWbemLocator”)
Set wmiNameSpace = wmiLocator.ConnectServer(“.”, “rootdefault”)
Set objRegistry = wmiNameSpace.Get(“StdRegProv”)
sPath = “SOFTWARECitrixIcaSession”

lRC = objRegistry.GetStringValue(HKEY_LOCAL_MACHINE, sPath, “ClientName”,sComputerName) ‘Query Registry for client name

‘set the environment variable
‘msgbox(sComputerName)

Set oShell = CreateObject(“WScript.Shell”)
Set oUserEnv = oshell.Environment(“User”)
oUserEnv(“CurrentPC”) = sComputerName
wscript.quit(0)

These scripts will search in the appropriate place in the registry for the name of the physical endpoint and establish it as an environment variable within the session called CurrentPC. Set this node to run at User Login after whichever node runs the PreviousPC = NULL action we set up in Step #1. After that, set it to run at either Session Reconnected (if you’re using View) or Session Unlocked (if you’re using XenDesktop).

Step #3:

Create a second node called “Set PreviousPC variable” and add an action to value the PreviousPC environment variable with %CurrentPC%. Set this node to be run at either the Session Disconnected trigger (if using View) or Session Locked trigger (if using XenDesktop).

With these two nodes configured as above, it is simply a matter of setting any location-sensitive actions (for example, printer mapping) to run dependent upon the condition that CurrentPC is not equal to PreviousPC.

To add actions to our metaphorical “location change trigger,” establish the aforementioned condition in any node you want, and then set all relevant actions to run if the condition passes. Finally, set these nodes to run after each iteration of the Set CurrentPC Variable nodes you created earlier.

The Logic for AppSense

In case the reasoning is not clear from the instructions above, the logic is basically as follows:

    1. User opens a new session. PreviousPC is set to NULL.
    2. CurrentPC is then valued with the name of the physical endpoint.
    3. AppSense sees that the two are not equal, and runs any actions that rely on that condition.
    4. User disconnects their session, and PreviousPC is set to be identical to CurrentPC.
    5. User reconnects their session, and CurrentPC is revalued with the name of the machine from which they are connecting.
    6. If they are reconnecting from the same machine,
      CurrentPC is re-set with the same value it previously contained. Because PreviousPC was set to contain that very value at the last disconnect, the variables are equal. AppSense does not run any actions.If, however, they are reconnecting from a new location,
      CurrentPC will be set to a new value. Because PreviousPC still contains the previous value of CurrentPC, these two values are no longer equal. AppSense runs the actions.
    7. Ipso facto, the actions are being triggered by a physical change of location, and not simply at reconnect. Voila, a location change trigger.

If you have actions that impact performance, this protocol should speed up your reconnect times by only running those actions when they are really needed.

Let me know if I lost you, or how this worked for you.

Adjust for Best Performance Using the Registry

In Windows XP, one was able to overwrite the Default users NTUSER.DAT with whatever one wanted and it would pretty much work okay. This meant you could just set “Adjust for best performance”  in the GUI with one user, and then overwrite the default NTUSER.DAT with this user’s modified verison. This changed with Windows 7, and it hasn’t been that simple since. Getting this setting to apply correctly in a Windows 7, linked clone/virtual desktop environment is far more complex than it should be.

Explanation

VMware recommends this setting get applied as a best practice, and even offers a Windows optimization script that attempts (unsuccessfully) to pull it off. As you are reading this, I can fairly assume you have noted your inability to make this change in a master image and have it affect your end-user. I can also guess that you have found a number of ways to use the registry to untick boxes in a GUI without actually applying the changes.

The standard responses I came across on various forums and articles pointed to a series of registry settings (UserPreferenceMask being the most commonly cited) which might have  worked for Windows XP (I honestly never checked), but which fail for Windows 7. While the information I found enabled me to make the “Use tools to improve performance” dialog simply look the way I wanted, I would have to actually click “Apply” before the changes would go into effect every time I got a desktop.

As it turns out, you need to touch an entire array of registry keys to adjust for best performance. A number of which are completely opaque and, at least for my part, indecipherable. You can hive these all out individually into the default user’s NTUSER.DAT file to enact the change, or if you are blessed enough to have AppSense at your disposal, you can create a node to run at Login and achieve the same effect.

Full disclosure: I am not entirely certain what some of these are actually doing, or whether Microsoft would advise against making these changes. I can, however, say that we have applied them in numerous environments without issue or complaint. Finally, I have not found any other means of setting the “adjust for best performance” option for an end-user without explicitly telling them to make the changes himself.

As with all registry hacks, use at your own risk, and don’t blame me if you manage to break something.

Adjust for Best Performance Registry Settings

You can find the required registry values here  (Pastebin).

Virtual Driver Error

I cannot decide if it is more infuriating to Google a problem and get no results or to get a single result that is not helpful in any way.

I came across this problem at a customer recently and the only thing the search giant could offer me was a singular thread on a forum somewhere that basically said “We had this problem. Then it went away and we can’t reproduce it. Nevermind I guess.”

Occasionally, a user would attempt to retrieve their XenDesktop session and would be met with “Virtual Driver Error” instead. This would disrupt the connection and the user would be unable to bring up their session. If they waited a sufficient amount of time and tried again, it worked. Rarely, trying again immediately worked as well. I was ultimately able to make the problem 100% reproducible. The customer had a mixed environment of these Wyse zero clients and PCs with Citrix Receiver agents (Enterprise v3.1) installed. If you spun up a new session from the PC, then tried to roam it to the Xenith, you would get the error. If you spun the session up on the Xenith, moved it to the PC and back, you would be fine.

I will spare you the troubleshooting steps that resulted in the following conclusion, but the fix was to change the color depth on the PCs from 32bit to 16bit (for Win7: Right click on desktop > Screen Resolution > Advanced Settings > Monitor tab). Once this fix was applied, we never saw the problem again. Reverting back immediately reintroduced it. To that end, if you have stumbled onto this post and elect to use this fix, we also found that the color depth setting did not get stored as part of the image for the PCs, and imaged machines had to be touched manually to apply the fix after the fact. Something to keep an eye on when deploying this.

If this, for whatever reason, is not an acceptable fix, I would encourage you to focus your troubleshooting on your display settings, either in terms of drivers installed locally or in your master image. This is as far as I went with this problem, but hopefully it’s a step in the right direction for someone more persistent. I was going to post it as a reply to the unhelpful thread (found here), but I didn’t feel like creating an account to do so.

If you find a better fix, leave a comment and let me know.

Caffeine

It’s about 2AM here in Bothell, WA. My friend told me that the Cuban coffee I drank at 6PM was going to keep me up all night and I confidently replied that my caffeine addiction would prevent such a thing from occurring.

I just registered a domain and started a blog. In that order.

The only people who will ever see this will be those bored enough to read back through the archives, having already found something more interesting that I haven’t come up with yet.

Hello time traveler. End of the line.

–Vince