Do you need to Live Migrate a Hyper-V guest from one unclustered host to another? Would you like to give your Hyper-V host the ability to directly mount ISO files from a file server or VMM library system? Do you ever need to do these things when you’re not logged on directly to the host that needs to perform these operations? Constrained delegation is a necessity.

Updated on February 6, 2017. Notes below the script and in the PowerShell help.

Briefly, delegation is the ability for one Active Directory computer to capture credentials from a currently-logged-on user and present them to a second computer. It’s similar to what CredSSP does except that it’s more secure and credentials can continue to be propagated as far as the allowed delegation chain extends. This is a powerful capability and is not to be used lightly. In order to restrict the impact of any potential compromise, constrained delegation allows you to select specific services that a computer can present credentials for. Unlike CredSSP, delegation requires a bit of effort on your part. The script included herein allows you to Configure Constrained Delegation for Hyper-V, find out the explanation below.

The GUI Way

The GUI, and some would say simple, way is to access the computer object in Active Directory Users and Computers and configure hosts using the Delegation tab. The following is taken from one of my Hyper-V hosts:

Constrained Delegation in ADUC

Constrained Delegation in ADUC

The host listed here (SVHV1) can present credentials to SVSTORE when performing SMB operations. It can present credentials to SVHV2 when performing unclustered Live Migration or SMB operations.

For just one or two hosts, doing this via ADUC isn’t too bad. More than a few can quickly get tiring, even for the most dedicated GUI-Only Clickmins. If you’re tempted to take the reduced-security shortcut of selecting Trust this computer for delegation to any service (Keberos only), I’ve been told that it doesn’t work for Live Migrations. I have not tested this myself because reducing security just because you don’t want to click is even worse than not using PowerShell because of whatever excuses people still have for not using PowerShell.

The Script Way

The sort of tedium and error-prone activity that is exemplified by clicking through constrained delegation screens is exactly what scripting is good for. Unfortunately, the Active Directory properties involved are not conducive to easy discovery or manipulation. So, I built a quick script that can take care of all the heavy lifting for you. All you have to do is save it to a .ps1 file (I assumed Set-VMHostADDelegation.ps1, but whatever you like), then dot-source it in to your environment.

The script has full Get-Help support, including examples.

Script Explanation

There is only one parameter set, and this how it looks:

The basic idea is that you’ll give the script one or more source computers, one or more destination computers, and tell it if you want to configure for SMB, Live Migration, or both.

As a point of clarification, the “Source” host is the one that you would open the ADUC dialog for; the “Target” is the computer that you would add to that computer’s dialog.

Because of the way that the ActiveDirectory PowerShell module auto-loads, I couldn’t just use any of its data types as input parameters. So, I set this script up to accept any object for a source and/or target. However, it expects that the object will be one or more Active Directory computer objects or one or more names of Active Directory computer objects. If it turns out that the supplied object is neither, the script will become upset and stop functioning until it gets what it wants. It will take short names or DNS names — really, anything that it can feed to Get-ADComputer’s Identity parameter.

Working from the assumption that you’d want all Hyper-V hosts that you supply to be able to perform operations on each other, I provided a Reciprocate parameter. If you use it, all items in both the source and target lists will be granted the specified delegation right on all other items in both lists. Because of this, I didn’t see any value in forcing you to specify a source and target list with the Reciprocate parameter. The script will accept the input if you do, but you can just put them all in TargetHost and not supply SourceHost at all.

If you’re not entirely certain what you’re about to do, don’t forget about the WhatIf parameter. I set it to explicitly show what will be changed by the script.

Changes in Version 1.1

I made a couple of substantial, but non-breaking changes in version 1.1.

First, Windows/Hyper-V Server 2016 does not work with constrained delegation set to Kerberos only. You can read John Slack’s article about it on TechNet. The claim is made that delegating to “any” protocol isn’t less safe than delegating to Kerberos only. On the surface, that doesn’t seem to hold a lot of water. I’m sure it’s fine if you’re only using delegation for its intended purpose. I’m not so sure it’s fine when someone is attempting to use delegation for more nefarious goals. I do not have the hacking chops to make that determination, though. All I know is that this is the new normal.

To address this change, I have added a parameter called “CompatibilityMode”. You can choose ‘2012’ or ‘2016’ for this parameter. It knows what the options are, so you can use tab completion and not type. If you do not enter this parameter, it will choose ‘2012’, which is delegation to Kerberos only. If you’d like, you can change the default. Just go to line 80 and swap in ‘2016’ where you see ‘2012’.

Second, I originally wrote the script to delegate to the complete DNS name of the target host(s). Some people said that didn’t work for them. They used the short names instead. The version of the script that I published has a parameter named “NamingMode” that allows you to choose between ‘DNS’ and ‘NetBIOS’. It will delegate accordingly. The default is ‘DNS’. You can change that default on line 81. I first tried to rewrite the script to allow delegation to both the short name and the DNS name, but it always knocks out any DNS names in favor of short names, if a short name is specified. That’s why the script doesn’t allow both.

Script Requirements

I am not certain exactly what permissions are required for configuring constrained delegation on an object, but just having Full Control on the object, its OU, and the target object is insufficient. I didn’t spend any time digging very deeply, but it appears that you really need to be a domain administrator.

The ActiveDirectory PowerShell module must be loaded. All of my domain controllers are running Server Core and I never log on to them directly. Instead, I have Remote Server Administration Tools configured on a couple of management systems. The PowerShell module is listed like this in 2012 R2 (it’s similar in all RSAT displays):

Active Directory PowerShell Module in RSAT

Active Directory PowerShell Module in RSAT

The ActiveDirectory PowerShell module sometimes behaves oddly when run in a remote PowerShell session, which, for me, means that it usually doesn’t work at all. I confess that I haven’t put a lot of effort into getting it to work. I built a management machine for a reason. So, if you use my script in a remote session and get strange errors, see if you can use Get-ADComputer in the same session. If not, that’s probably the root of the problem.