During my presentation at E2EVC in Berlin, we released new open source Powershell Desired State Configuration (DSC) resources for Citrix XenDesktop 7. Unfortunately for everyone there, I never actually finished the presentation.
The number of questions and level of interaction in the session was awesome. Even with the attempted sabotage by @drtritsch when he tried to blow the camera up, we recovered and soldiered on. Ultimately – having not completed the presentation and missing a few key implementation details – I thought it would be prudent to at least document how you can use the new resources! You know me – always a true professional :).
Credential Delegation
If you are using the new Citrix XenDesktop DSC resources in conjunction with WMF 4.0 then you will need to configure CredSSP on any machines that you will be installing the Citrix XenDesktop delivery controller role on. These machines will need to be configured to delegate credentials to all other delivery controllers and the Microsoft SQL server machine hosting the XenDesktop databases.
The reason for this is that the underlying Citrix XenDesktop PowerShell cmdlets have to run under Active Directory domain credentials. Unfortunately for us the DSC Local Configuration Manager (LCM) runs under the LOCALSYSTEM context and Citrix do not provide us with a –Credential parameter [sigh].
This means that we have to resort to using Powershell remoting to connect to local machine with alternate credentials! Unfortunately, this “loopback” mechanism means that if we subsequently attempt to connect to another XenDesktop delivery controller or even the Microsoft SQL server, we are subjected to the “double-hop” restriction.
You can see the “loopback” implementation details in the code. The majority of the custom resources invoke a script block on the local machine when credentials are supplied like so:
if ($Credential) { AddInvokeScriptBlockCredentials -Hashtable $invokeCommandParams -Credential $Credential; }
else { $invokeCommandParams['ScriptBlock'] = [System.Management.Automation.ScriptBlock]::Create($scriptBlock.ToString().Replace('$using:','$')); }
Write-Verbose ($localizedData.InvokingScriptBlockWithParams -f [System.String]::Join("','", @($Name, $Enabled, $Ensure)));
return Invoke-Command @invokeCommandParams;
Here, if the -Credential parameter is supplied in the configuration document then we add splatted parameters to invoke the script block on the local computer via remoting and specifying the credentials. If the –Credential parameter is not supplied then we just execute the script block as-is (after stripping out all the $using: statements).
Example Configuration
You can see an example of the CredSSP implementation in the example files used in the E2E presentation. Here, all node names in the $ConfigurationData that have a role of ‘Controller’ are put into an array (both NetBIOS and FQDN). Finally, the Microsoft SQL server’s name is added to ensure we can delegate credentials to create the databases.
## Need delegated access to all Controllers (NetBIOS and FQDN) and the database server
$credSSPDelegatedComputers = $ConfigurationData.AllNodes | Where Role -eq 'Controller' | ForEach {
Write-Output $_.NodeName
if ($_.NodeName.Contains('.')) { ## Output NetBIOS name as well
Write-Output ('{0}' -f $_.NodeName.Split('.')[0]);
}
else { ## Output FQDN as well
Write-Output ('{0}.{1}' -f $_.NodeName, $ConfigurationData.NonNodeData.XenDesktop.Site.DomainName);
}
};
$credSSPDelegatedComputers += $ConfigurationData.NonNodeData.XenDesktop.Site.DatabaseServer;
When enumerating the configuration for each delivery controller, for the first delivery controller we create the site and for all other delivery controllers we join the (now existing) site.
node ($AllNodes | Where Role -eq 'Controller' | Select -First 1).NodeName {
XD7LabSite FirstSiteController {
Credential = $Credential;
DatabaseServer = $ConfigurationData.NonNodeData.XenDesktop.Site.DatabaseServer;
DelegatedComputers = $credSSPDelegatedComputers;
LicenseServer = ($ConfigurationData.AllNodes | Where Role -eq 'Licensing' | Select -First 1).NodeName;
SiteAdministrators = $ConfigurationData.NonNodeData.XenDesktop.Site.Administrators;
SiteName = $ConfigurationData.NonNodeData.XenDesktop.Site.Name;
XenDesktopMediaPath = $Node.MediaPath;
}
...
}
...
node ($AllNodes | Where Role -eq 'Controller' | Select -Skip 1 | ForEach { $_.NodeName } ) {
XD7LabController AdditionalSiteController {
Credential = $Credential;
DelegatedComputers = $credSSPDelegatedComputers;
ExistingControllerAddress = ($ConfigurationData.AllNodes | Where Role -eq 'Controller' | Select -First 1).NodeName;
SiteName = $ConfigurationData.NonNodeData.XenDesktop.Site.Name;
XenDesktopMediaPath = $Node.MediaPath;
}
}
The list of computers to permitted to delegate credentials to is then passed to the composite DSC resource with the -DelegatedComputers parameter. Within the CitrixXenDesktop7Lab composite resources you can see the CredSSP implementation where the CredSSP client is actually configured:
Import-DscResource -ModuleName xCredSSP, CitrixXenDesktop7;
xCredSSP CredSSPServer {
Role = 'Server';
}
xCredSSP CredSSPClient {
Role = 'Client';
DelegateComputers = $DelegatedComputers;
}
Easy when you know how, eh?! Just remember that how you configure CredSSP is up to you and you don’t have to use the xCredSSP DSC resource; you could use Group Policy if you wanted to. Just remember that if you’re running WMF 4.0 then CredSSP has to be configured somehow!
WMF 5.0
If you’re lucky enough to be able to use WMF 5.0 then all this CredSSP configuration becomes a moot point. In the latest WMF 5.0 preview the Powershell team added a default -PsDscRunAsCredential parameter to all resources that handles the impersonation for us. Yay! \o/
This means that if you use the CitrixXenDesktop7 DSC resources on WMF 5.0 machines you should not specify the –Credential parameter in your configuration, but leverage the built-in -PsDscRunAsCredential parameter instead. This also means that the xCredSSP resources is no longer required and can be removed from your configuration or any composite DSC resources.
Remember, the CitrixXenDeskop7 and CitrixXenDesktop7Lab resources are open-source projects. We would love to see the community contribute, add resources and round out the implementation. Join us and get involved!