This blog will be of interest to both scripters and programmers who wish to use the XenApp 6 SDK to configure a farm remotely.

By now, those who have been following my blog should have gotten their feet wet in the XenApp 6 PowerShell SDK. But for those familiar with MFCOM, you are probably wondering what happened to a major bit of functionality that MFCOM had: the ability to remotely configure a farm with a script that runs on a different computer. I have alluded to this upcoming blog a few times so I hope people will not be disappointed!

When we started implementing the XenApp 6 SDK, we knew that this would be a major requirement. We also had a very aggressive schedule in which to complete our SDK. At the time, we also knew that Microsoft was planning to introduce automatic remoting capability for PowerShell. Putting 2 + 2 together, we decided to focus on getting the command implementation right, and trust in the availability of PowerShell Remoting to solve the remote management side of things.

Indeed, PowerShell 2.0 was released by the time we shipped the XenApp 6 SDK, and for the most part it does meet the remoting needs of our SDK. It does have a much more complex configuration than we would have hoped, and we did find one major limitation that we unfortunately do not have a good workaround for yet; but overall, PowerShell Remoting delivers a comprehensive remoting capability for the XenApp 6 SDK.

First of all, about the limitation I mentioned: we discovered that PowerShell Remoting does not work when invoked from a service with limited privileges, such as a web service running under the control of IIS. We did not have time to resolve this issue prior to the release of XenApp 6 nor the XenApp 6 SDK. If this is the scenario you are facing, the only workarounds available at the moment are to use the undocumented and unsupported XACOM API, or to write your own elevated service through which you delegate calls to the XenApp SDK. I assure you we will fix this by the next release of XenApp.

The other drawback I mentioned in comparison to MFCOM is the difficulty of configuration. With COM/DCOM, the only thing you needed to do to enable remote management was to add users to the Remote DCOM Users group (or Distributed COM Users group, depending on the version of Windows). Although, in truth, there was quite a bit more that we did under the covers to make sure the experience was good, such as creating firewall exclusion rules to handle MFCOM traffic. However with PowerShell, much more is required:

  1. The server must have the WinRM service enabled and started.
  2. The server’s firewall must allow https traffic to pass to the WinRM service.
  3. To secure the client-server communications, the server must have an SSL certificate. This certificate cannot be self-signed without causing a significantly worse user experience for the PowerShell remoting user. (Note: there are ways to avoid having an SSL certificate but it seems that all of these options do not thoroughly secure client-server communications, even if the client and server are in the same domain. Therefore, I will only discuss secure remoting methods that utilize an SSL certificate.)
  4. The server must have an Endpoint configuration with appropriately locked-down configuration.
  5. The client must be able to identify the server through a trusted authority (via the SSL certificate publishing authority).
  6. The client must trust the server.
  7. The client must create a remote session on the server in order to use remoting.

Microsoft recognized that some of these steps are quite complex, so they provide a script with PowerShell 2.0 called Enable-PSRemoting. Although this script will work to enable remoting for PowerShell, and XenApp commands can work within the endpoint configuration that this script creates, it will set up the remoting configuration in a way that is only available to (and only suitable for) local administrators. Since we require support for XenApp administrators who are not also local administrators, we created our own equivalent to this command. Additionally, the configuration that Enable-PSRemoting creates is not secured with an SSL certificate by default, and therefore can be compromised – a configuration we were not willing to support or endorse. As part of the XenApp 6 SDK, we therefore provide a script named Enable-XAPSRemoting that creates a configuration that is XenApp-SDK specific, and does not have these limitations.

Enable-XAPSRemoting does not require you to have run Enable-PSRemoting first. It does require that you have set your PowerShell script execution policy to AllSigned, RemoteSigned, or Unrestricted. If you choose AllSigned you must opt to “[A] Always run” if presented with this question:

Do you want to run software from this untrusted publisher?
File C:\Program Files\Citrix\XenApp Server SDK\Citrix.XenApp.Sdk.ps1 is published by CN=”Citrix Systems, Inc.”, OU=AVG Bangalore, OU=Digital ID Class 3 – Microsoft Software Validation v2, O=”Citrix Systems, Inc.”, L=Fort Lauderdale, S=Florida, C=US and is not trusted on your system. Only run scripts from trusted publishers.
[V] Never run [D] Do not run [R] Run once [A] Always run [?] Help (default is “D”):

Prior to running Enable-XAPSRemoting, you must first complete a step for which we cannot provide much assistance: you must install an SSL certificate on the server. Consult Microsoft documentation on deploying a Public Key Infrastructure within your organization, if you don’t already have one. You will need a certificate server, and all servers and clients will need to trust that authority. Then that certificate authority can authorize a proper SSL certificate for the server, which the clients and the server will all recognize as being legitimate.

For testing purposes ONLY, we have simplified the process of using a self-signed certificate. This can be used to get a proof-of-concept remoting solution up and running quickly. However, be aware that a self-signed certificate is not secure.

That being said, in case you must use a self-signed certificate for the time being in order to proceed following along with this blog, you can create one easily using the selfssl.exe tool that Microsoft distributes as part of the IIS 6 Resource Kit. This can be downloaded from here. You should run the tool on the server:

selfssl.exe /T /V:365

This will create and install a self-signed certificate valid for 1 year (365 days) and install it into the trusted certificate store on the server.

Of course, if you already have a public key infrastructure in place, save yourself the trouble of changing the certificate later by just creating a valid certificate now and installing it in the server’s certificate store.

Once you have the SSL certificate in place, you can run the Enable-XAPSRemoting script.

Enable-XAPSRemoting

This script will prompt you for the SSL certificate to use for the WinRM SSL listener. The one you added above should be visible; choose it. If it is not visible, verify that the certificate is installed correctly using the Certificate Manager tool available in Windows. It should be visible under “Trusted Root Certification Authorities”.

Once the script completes, your server will be ready to accept remote connections from local administrators. Of course, as mentioned above, XenApp administrators are not always local administrators, so you also have the ability to open up the remote channel to the XenApp administrators you choose by adding users into the “Citrix Remote PowerShell Users” user security group. If you use Active Directory, it is highly recommended that you create AD group(s) to represent Citrix XenApp administrators and enter those groups both here and in the Administrator configuration in XenApp itself, so that it is simpler to keep the two in sync. (Of course, you may not want to keep these in sync, if you want to limit remote SDK access to a select few.)

It is important to explain the security on the endpoint configuration that the script creates.

  • The users present in the Citrix Remote PowerShell Users group are not automatically granted privileges as XenApp administrators; rather, they are given permission to run the XenApp SDK cmdlets. The cmdlets themselves, and in fact even the back-end storage layer, still validate the identity of the user prior to allowing the user to view or edit data. So, even if the membership of the Citrix Remote PowerShell Users group is wider than the actual set of XenApp Administrators, your farm is still secure.
  • The configuration only allows a very limited subset of commands to be executed remotely; in fact, hardly anything is available except the XenApp commands themselves. This ensures that other installed cmdlets that may not have as deep of a security model are not exposed to users that should not have access to them.
  • The configuration turns off PowerShell language features such as looping constructs. This limits the capability of users from being able to perform denial-of-service attacks using the exposed endpoint.

As you can see, the endpoint we create is as secure as possible. The tradeoff is that the endpoint can be used only for XenApp commands, and only by approved administrators. The endpoint is neither suitable nor intended for usage of other PowerShell commands or snap-ins.

Once the script completes, the server is prepared to accept remote PowerShell connections for the XenApp commands. The next step is to make the client trust the server, so that it will allow you to connect to it. On the client, run this command:

Set-TrustedHosts <server>

This tells PowerShell to trust the specified host. If you want the client to trust any host, you can use “*” for the server name. The client will verify that the host is actually the one you specified by checking the authenticity of its SSL certificate, so make sure that the server name you specify (if not “*”) matches the host name in the SSL certificate.

At this point, remoting should be fully operational. To test it out, we will create a remote session and use that to execute commands on the server, from the client. PowerShell has a built-in command called New-PSSession which has all the functionality required; however, it is not very simple to use. We therefore created a simpler version with the most frequently used options, called New-XAPSSession:

$session = New-XAPSSession <server> -SkipCertCheck

The -SkipCertCheck option turns off all SSL certificate checking, and is necessary if you wish to use a self-signed certificate. Of course if you are using a certificate from a trusted issuer (such as from your organization’s public key server), you should omit the -SkipCertCheck option.

Within the session that you created, you can execute any Citrix command on the server. For instance:

Invoke-Command -Session $session { Get-XAFarm }

We also expose the Get-Help command within the session, so you can do:

Invoke-Command -Session $session { Get-Help Get-XAFarm }

We do not expose aliases, so you must explicitly use Get-Help rather than the common help alias.

You can also try:

Invoke-Command -Session $session { Get-Command }

This will print out all of the commands that are available through the default XenApp remote PowerShell configuration. You will notice that it only includes commands from the Citrix.XenApp.Commands snap-in; it does not include commands from the Citrix.Common.Commands snap-in, nor any commands capable of interacting with the Citrix.Common.GroupPolicy provider. The reason is that the commands in Citrix.Common.Commands are not remotable even via PowerShell remoting, due to impersonation limitations, and the Citrix.Common.GroupPolicy provider can edit remote GPOs without using PowerShell remoting. You will instead find that both of these snap-ins are installed locally on the client when you install the XenApp SDK.

One final shortcut: if you are only targeting one server from your client, and you want to avoid the Invoke-Command hassle, you can do:

Import-PSSession -Session $session

You’ll now find the Citrix commands available within your local PowerShell window, but when you execute them, they automatically execute on the server.

I hope this information helps people get started using PowerShell remoting for the XenApp SDK. Please let me know if you have any questions!

Note for programmers: I will cover the differences when using the XenApp SDK via PowerShell remoting from within a .NET program in my next blog. However the setup steps and capabilities are the same as that used by scripters.