I've been modifying a local fork of the Tridion Powershell Module to work with a preview version of 2013. This is mostly a matter of fixing up the binding and endpoint to the relevant 2013 values. At the same time I have been adding support for the netTcp binding (which leads to more error information later in this question).
Prior to this modification work, I had been working with a simpler function to get a core service client in the Powershell:
$coreServiceClientPath = `
'C:\Program Files (x86)\Tridion\bin\client\CoreService\Tridion.ContentManager.CoreService.Client.dll'
function get-Core {
Add-Type -assemblyName System.ServiceModel
$binding = new-object System.ServiceModel.NetTcpBinding
$binding.MaxBufferPoolSize = [int]::MaxValue
$binding.MaxReceivedMessageSize = [int]::MaxValue
$binding.ReaderQuotas.MaxArrayLength = [int]::MaxValue
$binding.ReaderQuotas.MaxBytesPerRead = [int]::MaxValue
$binding.ReaderQuotas.MaxNameTableCharCount = [int]::MaxValue
$binding.ReaderQuotas.MaxStringContentLength = [int]::MaxValue
$endpoint = new-object System.ServiceModel.EndpointAddress `
net.tcp://localhost:2660/CoreService/2012/netTcp
Add-Type -Path $coreServiceClientPath
new-object Tridion.ContentManager.CoreService.Client.SessionAwareCoreServiceClient `
$binding,$endpoint
}
This works just fine, being very simple, however, when I came to port the module to 2013, I realised that the .Impersonate()
call gives some trouble.
The function Get-TridionCoreServiceClient uses Impersonate() as follows:
$proxy = New-Object $serviceInfo.ClassName -ArgumentList $binding, $endpoint;
Write-Verbose ("Connecting to the Core Service as {0}" -f $serviceInfo.UserName);
$proxy.Impersonate($serviceInfo.UserName) #| Out-Null;
Where UserName is ([Environment]::UserDomainName + "\" + [Environment]::UserName)
This invocation works fine in 2011, and my get-core
function which does not impersonate works fine, but in 2013, this approach results in an error condition. Here's the output (with some minor edits)
PS C:\Users\Administrator> Get-TridionCoreServiceClient -protocol http
Connecting to the Core Service at localhost...
Get-TridionCoreServiceClient : The HTTP request is unauthorized with
client authentication scheme 'Anonymous'. The
authentication header received from the server was 'Negotiate,NTLM'.
Microsoft.PowerShell.Commands.WriteErrorException,Get-TridionCoreServiceClient
PS C:\Users\Administrator> Get-TridionCoreServiceClient -protocol nettcp
Connecting to the Core Service at localhost...
Get-TridionCoreServiceClient : The socket connection was aborted.
This could be caused by an error processing your
message or a receive timeout being exceeded by the remote host,
or an underlying network resource issue. Local socket
timeout was '00:00:59.9958624'.
As you can see, the error output is different depending on the protocol you choose. For the netTcp variant, we also see the following in the Tridion Windows event log:
Stream Security is required at http://www.w3.org/2005/08/addressing/anonymous,
but no security context was negotiated. This is likely caused by the remote
endpoint missing a StreamSecurityBindingElement from its binding.
If I comment out the call to $proxy.Impersonate()
, everything works fine. What differences are there between 2013 and 2011 that might cause the impersonation to fail like this? How should I correctly use the 2013 API?
Edit: Looks like Pankaj is right. Commenting out the call to impersonate isn't so relevant. I now have netTcp working OK - it turned out that the $binding.Security.Mode and $binding.Security.Transport.ClientCredentialType settings weren't needed for this protocol.
I'm still having trouble with HTTP. As noted before the error message is: The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'Negotiate,NTLM'.
I've tried setting the security mode to Transport, but that just gets me a different error. Time to post a bounty and see if any WCF folks wander by!