Remote PowerShell Proxying Behavior in Exchange 2013 CU12 and Exchange 2016
Published Mar 01 2016 09:00 AM 50.8K Views
Microsoft

In Exchange 2013 CU11, we introduced a change to the way Remote PowerShell (RPS) functioned.

Prior to CU11, Exchange 2013 routed Remote PowerShell requests by finding a random mailbox that is either higher than the ExchClientVer that is specified in the URL, or if the ExchClientVer is not specified, by using the current CAS version in which the client connected. We refer to this behavior as server version-based routing.

With CU11, we changed Remote PowerShell to route requests to an anchor mailbox. Typically, this anchor mailbox would be the mailbox of the user attempting the connection. In the event the user attempting the connection did not have a mailbox, the request would be routed to the organization arbitration mailbox.

There were several perceived benefits with this approach:

  1. This approach solved an issue with coexistence and ensured that RPS is executed based on the version of the mailbox executing the action. The server version-based routing behavior prior to CU11 led to scenarios where a client could receive the following error:

    New-PSSession : [ems.contoso.com] Processing data from remote server ems.contoso.com failed with the
    following error message: [ClientAccessServer=E2K13-1,BackEndServer=e2k13-1.contoso.com,RequestId=76229690-2343-4
    f-9a51-48184587c5cf,TimeStamp=8/14/2015 2:20:36 PM] [FailureCategory=WSMan-InvalidShellID] The request for the Window
    Remote Shell with ShellId DD266254-5C1F-43C0-A4DA-1797C253C0C0 failed because the shell was not found on the server.
    Possible causes are: the specified ShellId is incorrect or the shell no longer exists on the server. Provide the
    correct ShellId or create a new shell and retry the operation. For more information, see the
    about_Remote_Troubleshooting Help topic.
    At C:\Scripts\test.ps1:8 char:12
    + $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri ht ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : OpenError: (System.Manageme....RemoteRunspace:RemoteRunspace) [New-PSSession], PSRemoti
    gTransportException
    + FullyQualifiedErrorId : CannotConnectTargetSessionDoesNotExist,PSSessionOpenFailed
    Import-PSSession : Cannot validate argument on parameter 'Session'. The argument is null. Provide a valid value for
    the argument, and then try running the command again.
    At C:\Scripts\test.ps1:10 char:18
    + Import-PSSession $Session
    + ~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Import-PSSession], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.ImportPSSessionCommand

    This error occurs when a load balanced RPS request shifts from one version of Exchange to another, whether that be Exchange 2013 coexisting with Exchange 2016, or different versions of cumulative updates for the same version of Exchange.

  2. This approach utilized the same code path for Remote PowerShell proxying in Office 365.

Unfortunately, the changes in CU11 introduced several issues with Remote PowerShell in the on-premises world that we did not anticipate. After reviewing each issue and performing an in-depth code review, we made the decision to revert the CU11 change and return to utilizing server version-based routing for Remote PowerShell requests beginning in Exchange 2013 CU12. Exchange 2016 (including CU1) will also use server version-based routing.

If you were planning to take advantage of the changes in Remote PowerShell routing in CU11, you may now be wondering what options are available to you beginning in CU12. Fortunately, you have several options:

  1. When connecting to Exchange via Remote PowerShell, specify a server FQDN instead of a load balanced namespace.

    $cred = Get-Credential
    $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://servername.contoso.com/powershell -Authentication Kerberos -Credential $cred
    Import-PSSession $Session

    For more information, please see the TechNet article, Connect to Exchange servers using Remote PowerShell.

  2. When connecting to Exchange via Remote PowerShell and specifying a load balanced namespace, specify the ExchClientVer value for the server version you wish to connect against.

    $cred = Get-Credential
    $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri “https://lb.contoso.com/powershell?serializationlevel=Full;ExchClientVer=15.0.225.0" -Authentication Basic -Credential $cred
    Import-PSSession $Session

  3. Configure the load balancer to use session affinity for Remote PowerShell requests.
  4. Remove the older Exchange versions from the load balanced pool.

We will continue to evaluate ways we can improve the routing of Remote PowerShell requests for on-premises deployments.

Ross Smith IV
Principal Program Manager
Office 365 Customer Experience

8 Comments
Not applicable
Which session affinity type do you recommend for RPS? We are currently using the MS-WSMAN cookie.
Not applicable
@krisasmith - cookie is good.
Not applicable
Thanks for listening to the feedback!
Not applicable
Nice information about remote powershell behaviour in Exchange 2013 CU11.
Not applicable
awasame
Not applicable
Good to hear that
Not applicable
Great article.. would like to have more options !!!!
Brass Contributor

@Ross Smith IV  not something that I would do usually. However unable to find any good references for this and this is the closest I can find.

In the reference article of yours there is a clear Note: The ConnectionUri value is http, not https.

Connect to Exchange servers using Remote PowerShell.

 

However the sample Uri that you have on this articles are all https, is that a typo or something more you can help us understand. If its intentional, pointing to any existing documentation would help or maybe a fresh article published.

 

Moreover, it should become the new default and move away from secure HTTP via Kerberos. It would save some time spent with security teams for port 80 discusssions.

 

Version history
Last update:
‎Jul 01 2019 04:26 PM
Updated by: