Set-KCD; configuring Kerberos Constrained Delegation (KCD)
In June I posted an article called Configuring Kerberos Constrained Delegation for Hyper-V Management. I covered the concept of Kerberos delegation and evolution into constrained delegation. Obviously, the article was mainly focused on configuring constrained delegation for Hyper-V management in order to be able to manage Hyper-V in a remote fashion. I ended the article with a PowerShell script called Set-KCD.ps1 and Active Directory cmdlet to configure KCD and verify successful delegation.
I primarily use PowerShell for management and therefore use my own scripts. Using Set-KCD worked well but it lacked certain capabilities which resulted in performing additional steps from the PowerShell command line. Like I mentioned in the article, it was nothing fancy or advanced but it worked in its limited way.
My environment is being reinstalled from time to time. This time it was because of the availability of the release of Windows Server 2012. Sometimes, if possible, I use upgrades. But upgrade was not possible so I reinstalled the environment. I could have upgraded Active Directory but a reinstallation and reconfiguration was actually even faster in my simple environment.
So I needed to configure KCD for my hosts and noticed this script could be improved. I rewrote the script such that it would be much easier to use. For example using a distinguished name for the Active Directory computer object is not intuitive and also requires additional Active Directory cmdlets to find the object path. The computer object can be located anywhere in Active Directory and will usually not exist in the Computers container.
The parameter names for the computers where also not intuitive. The computer you configure to be trusted for delegation was called ‘AdDN’ (the Active Directory Distinguished Name) and the computer you specify to trusted delegation to was called HostFQDN. So I changed this into TrustedComputer and TrustingComputer respectively. The thought was this: you configure the computer object in Active Directory to be trusted for delegation of your credentials to a specific computer for a specific service type. So TrustedComputer is self explanatory here. The computer you specify to allow delegation to for a specific service type is basically the computer that trusts the TrustedComputer for delegation. Although the graphical tools in Active Directory don’t use these terms, I think it is the easiest to understand using these terms when configuring KCD. A small change has been made to the service parameter which is now called ServiceType since this is what it really refers to.
I removed the requirement for fully qualified names. You must be logged on as domain administrator so I get the domain name from the logon session. The result is that the command has become much simpler and easier to understand. Referring to the picture in the previous post, when configuring KCD for vmhost1 to be trusted for CIFS to vmhost2, the command looks like this:
./Set-KCD –TrustedComputer vmhost1 –TrustingComputer vmhost2 –ServiceType CIFS –Add
or just type:
./Set-KCD vmhost1 vmhost2 CIFS
This is much simpler compared to the old command syntax:
./Set-KCD –AdDN “cn=vmhost1,cn=computers,dc=contoso,dc=com” –HostFQDN vmhost2.contoso.com –Service CIFS –Add
Finally, I also wanted to be able to configure delegation records for multiple computer objects in one step and to be able to verify the settings so I added the option to import the settings from a file.
The following switches are available:
- -Add
- -Clear
- -Import
- -List
- -ListFromFile
- -Remove
- -Replace
I will not go into the details of each. Because of the built-in help of the script you can get the syntax, examples or full description using ‘help ./Set-KCD’, ‘help ./Set-KCD' –examples’ or ‘help ./Set-KCD –full’.
There are four new switches; –Clear, –Import, –List, –ListIFromFile.
Clear will simply clear all delegation records of the TrustedComputer.
List displays the delegation records currently configured for the TrustedComputer.
ListFromFile displays the delegation records for all TrustedComputer entries in the File.
Import enables you to configure delegation records for multiple trusted computers at once. This is one I use for my environment to configure KCD using a configuration file. The –File property lets you specify a path to a CSV file containing the records for the TrustedComputer, TrustingComputer and ServiceType. The format of the file is documented in the help and a sample file is included in the Set-KCD zip file.
Below is the updated script. It also contains some basic error handling but it won’t check your privileges.
Code Snippet
- #######################################################
- ##
- ## Set-KCD.ps1, v1.2, 2012
- ##
- ## Created by Matthijs ten Seldam, Microsoft
- ##
- #######################################################
- <#
- .SYNOPSIS
- Configures Kerberos Constrained Delegation (KCD) on a single computer object or multiple computer objects in Active Directory.
- .DESCRIPTION
- Set-KCD supports adding, replacing, removing, clearing and listing of delegation records for a specified computer object or multiple computer objects in Active Directory.
- .PARAMETER TrustedComputer
- The name of the computer object in Active Directory trusted for delegation to a specific service type.
- .PARAMETER TrustingComputer
- The name of the computer to delegate authentication to. This is the computer that will accept your credentials on behalf of the TrustedComputer.
- .PARAMETER ServiceType
- The name of the ServiceType to delegate.
- .PARAMETER Add
- Switch to specify to add delegation records.
- .PARAMETER Clear
- Switch to specify to clear delegation records.
- .PARAMETER File
- The name of a CSV file containing entries for the Trusted and Trusting computers and the ServiceType.
- .PARAMETER Import
- Switch to specify to import delegation records.
- .PARAMETER List
- Switch to list current delegation settings for the specified TrustedComputer.
- .PARAMETER lISTfROMfILE
- Switch to list current delegation settings for the TrustedComputer entries spcified in the File.
- .PARAMETER Remove
- Switch to specify to remove delegation records.
- .PARAMETER Replace
- Switch to specify to replace delegation records.
- .EXAMPLE
- Set-KCD -TrustedComputer vmhost1 -TrustingComputer vmhost2 -ServiceType cifs -Add
- This command adds the CIFS ServiceType type to the computer object vmhost1 for computer vmhost2 to trust vmhost1 for delegation to vmhost2 for this ServiceType.
- .EXAMPLE
- Set-KCD.ps1 -TrustedComputer vmhost2 -TrustingComputer vmhost3 -ServiceType "Microsoft Virtual System Migration ServiceType" -Add
- This command adds the "Microsoft Virtual System Migration ServiceType" type to the computer object vmhost2 for computer vmhost3 to trust vmhost2 for delegation to vmhost3 for this ServiceType.
- .EXAMPLE
- Set-KCD -TrustedComputer vmhost1 -TrustingComputer vmhost2 -ServiceType cifs -Replace
- This command replaces ALL delegation properties with the specified property set (vmhost2/cifs). Any existing properties will be removed.
- .EXAMPLE
- Set-KCD -TrustedComputer vmhost1 -TrustingComputer vmhost2 -ServiceType cifs -Remove
- This command removes the specified delegation properties for vmhost2 and cifs.
- .EXAMPLE
- Set-KCD -TrustedComputer vmhost3 -Clear
- This command clears ALL property sets currently specified for delegation.
- .EXAMPLE
- Set-KCD -TrustedComputer vmhost1 -List
- This command lists the available property sets (service type | computer name) on the object of computer vmhost1 (if anything has been configured).
- .EXAMPLE
- Set-KCD -File .\ConfigFile.csv -ListFromFile
- This command uses the TrustedComputer entries in the File to list the currently configured delegation records.
- .EXAMPLE
- Set-KCD -File .\ConfigFile.csv -Import
- This command uses the contents in the CSV File to configure the TrustedComputer with delegation records for the TrustingComputer and ServiceType.
- See below example for a correctly formatted file:
- TrustedComputer,TrustingComputer,ServiceType
- vmhost1,fhost1,CIFS
- vmhost1,vmhost2,Microsoft Virtual System Migration Service
- vmhost1,vmhost2,CIFS
- vmhost2,vmhost1,Microsoft Virtual System Migration Service
- vmhost2,vmhost1,CIFS
- .INPUTS
- None
- .OUTPUTS
- None
- .NOTES
- This script must be run using domain administrator credentials.
- The script adds both entries for the target computer; unqualified and fully qualified computer names.
- The script uses the UserDnsDomain environment variable to construct the fully qualified domain name of the TrustingComputer name.
- .LINK
- https://blogs.technet.com/matthts
- #>
- [CmdletBinding(DefaultParameterSetName="Add")]
- param(
- [Parameter(Mandatory=$true, Position=0, ParameterSetName="Add")]
- [Parameter(Mandatory=$true, Position=0, ParameterSetName="Clear")]
- [Parameter(Mandatory=$true, Position=0, ParameterSetName="List")]
- [Parameter(Mandatory=$true, Position=0, ParameterSetName="Remove")]
- [Parameter(Mandatory=$true, Position=0, ParameterSetName="Replace")]
- [string] $TrustedComputer,
- [Parameter(Mandatory=$true, Position=1, ParameterSetName="Add")]
- [Parameter(Mandatory=$true, Position=1, ParameterSetName="Replace")]
- [Parameter(Mandatory=$true, Position=1, ParameterSetName="Remove")]
- [string] $TrustingComputer,
- [Parameter(Mandatory=$true, Position=2, ParameterSetName="Add")]
- [Parameter(Mandatory=$true, Position=2, ParameterSetName="Replace")]
- [Parameter(Mandatory=$true, Position=2, ParameterSetName="Remove")]
- [string]$ServiceType,
- [Parameter(Mandatory=$false, ParameterSetName="Add")]
- [switch]$Add,
- [Parameter(Mandatory=$true, ParameterSetName="Clear")]
- [switch]$Clear,
- [Parameter (Mandatory=$true, ParameterSetName="Import")]
- [Parameter (Mandatory=$true, ParameterSetName="ListFromFile")]
- [string]$File,
- [Parameter (Mandatory=$true, ParameterSetName="Import")]
- [switch]$Import,
- [Parameter(Mandatory=$true, ParameterSetName="List")]
- [switch] $List,
- [Parameter(Mandatory=$true, ParameterSetName="ListFromFile")]
- [switch] $ListFromFile,
- [Parameter(Mandatory=$true, ParameterSetName="Remove")]
- [switch] $Remove,
- [Parameter(Mandatory=$true, ParameterSetName="Replace")]
- [switch] $Replace
- )
- Set-StrictMode -Version Latest
- If ($PSCmdlet.ParameterSetName -ne "Import")
- {
- If ($TrustedComputer.Contains("."))
- {
- $TrustedComputer=$TrustedComputer.Remove($TrustedComputer.IndexOf("."))
- }
- }
- Function Get-Delegation()
- {
- try
- {
- $AdObject = Get-AdComputer $TrustedComputer -Properties msDS-AllowedToDelegateTo | Select-Object -ExpandProperty msDS-AllowedToDelegateTo
- If ($AdObject -ne $null)
- {
- Write-Host `n"Computer name $TrustedComputer is trusted for delegation for the following service(s) to computer(s):"
- Write-Host "--------------------------------------------------------------------------------------------"`n
- $AdObject | Sort-Object
- Write-Host `n"--------------------------------------------------------------------------------------------"`n
- }
- else
- {
- Write-Host `n"No delegation has been configured for computer $TrustedComputer."`n
- }
- }
- Catch
- {
- Write-Host `n"An error occurred searching for Computer name $TrustedComputer in Active Directory!"`n
- }
- }
- switch($PSCmdlet.ParameterSetName)
- {
- {($_ -eq "Add") -or ($_ -eq "Replace") -or ($_ -eq "Remove")}
- {
- If ($TrustingComputer.Contains("."))
- {
- $TrustingComputer=$TrustingComputer.Remove($TrustingComputer.IndexOf("."))
- }
- try
- {
- $ParamHash=@{$PSCmdlet.ParameterSetName=@{"msDS-AllowedToDelegateTo"="$ServiceType/$TrustingComputer","$ServiceType/$TrustingComputer.$env:UserDnsDomain"}}
- Get-ADComputer $TrustedComputer | Set-ADObject @ParamHash
- Get-Delegation
- }
- Catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException]
- {
- Write-Host "`nThe Object for computer $TrustedComputer could not be found in Active Directory.`n"
- }
- }
- "Clear"
- {
- Get-ADComputer $TrustedComputer | Set-ADObject -Clear msDS-AllowedToDelegateTo
- Get-Delegation
- }
- "Import"
- {
- If ($File -ne $null)
- {
- try
- {
- $Records=Import-Csv $File
- }
- Catch
- {
- Write-Host `n"$File file not found!`n"
- exit
- }
- foreach($Item in $Records)
- {
- $TrustedComputer=$Item.TrustedComputer
- $TrustingComputer=$Item.TrustingComputer
- $ServiceType=$Item.ServiceType
- Get-ADComputer $TrustedComputer | Set-ADObject -Add @{"msDS-AllowedToDelegateTo"="$ServiceType/$TrustingComputer","$ServiceType/$TrustingComputer.$env:UserDnsDomain"}
- Write-Host "--------------------------------------------------------------------------------------------"`n
- Write-Host "Added $ServiceType/$TrustingComputer,$ServiceType/$TrustingComputer.$env:UserDnsDomain to $TrustedComputer."`n
- }
- }
- }
- "List"
- {
- Get-Delegation
- }
- "ListFromFile"
- {
- If ($File -ne $null)
- {
- try
- {
- $Records=Import-Csv $File | Select-Object -Property TrustedComputer -Unique
- }
- Catch
- {
- Write-Host `n"$File file not found!`n"
- exit
- }
- foreach($Item in $Records)
- {
- $TrustedComputer=$Item.TrustedComputer
- Get-Delegation
- }
- }
- else
- {
- Get-Delegation
- }
- }
- }
This is for reference only. You can download the script and sample configuration file here.
Comments
- Anonymous
December 18, 2014
Thanks. You saved us a lot of development, testing and manual entries on this topic. - Anonymous
February 09, 2015
Excellent tool - going to save me a lot of time as I add more hosts to our environment! - Anonymous
July 16, 2015
Thanks. It is very helpful.