7

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!

3 Answers 3

5

I can also confirm that the Impersonate method is not available in 2011 SP1. My powershell code:


$URI = "http://localhost/webservices/CoreService2011.svc?wsdl" 
$pass = ConvertTo-SecureString "MyPassword" -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential -argumentlist "MyDomain\Administrator", $pass
$wcf = New-WebServiceProxy -uri $URI -namespace CoreService -Credential $mycreds 
$readOptions = New-Object CoreService.ReadOptions
$wcf.Impersonate("MyDomain\Editor");
"Current user: " + $wcf.GetCurrentUser().Id

Results in:


Method invocation failed because [CoreService.basicHttp] doesn't contain a method named 'Impersonate'.
At C:\Development\Projects\Powershell\CoreService.ps1:6 char:17
+ $wcf.Impersonate <<<< ("MyDomain\Editor");
    + CategoryInfo          : InvalidOperation: (Impersonate:String) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound

Furthermore, getting the list of available methods:

$wcf | get-member -type method

Does not contain the Impersonate method (see excerpt):


GetWorkItemSnapshot                       Method     CoreService.RenderedItemData, z15modu2, Version=0.0.0.0, Culture=ne...
GetWorkItemSnapshotAsync                  Method     System.Void GetWorkItemSnapshotAsync(string workItemId), System.Voi...
InitializeLifetimeService                 Method     System.Object InitializeLifetimeService()
IsExistingObject Method System.Void IsExistingObject(string id, System.Boolean&, mscorlib, ... IsExistingObjectAsync Method System.Void IsExistingObjectAsync(string id), System.Void IsExistin... IsPublished Method System.Void IsPublished(string itemId, string publicationTargetId, ... IsPublishedAsync Method System.Void IsPublishedAsync(string itemId, string publicationTarge... IsValidTridionWebSchemaXml Method System.Void IsValidTridionWebSchemaXml(CoreService.SchemaData, z15m... IsValidTridionWebSchemaXmlAsync Method System.Void IsValidTridionWebSchemaXmlAsync(CoreService.SchemaData,... Localize Method CoreService.RepositoryLocalObjectData, z15modu2, Version=0.0.0.0, C... LocalizeAsync Method System.Void LocalizeAsync(string id, CoreService.ReadOptions, z15mo... Move Method CoreService.RepositoryLocalObjectData, z15modu2, Version=0.0.0.0, C...

3
  • 3
    From your error message it seems that you use basicHttp. As far as I know Impersonate has never been available over a basicHttp connection, but only in the SessionAwareCoreServiceClient. Impersonation allows your code to assume the identity of any user, without specifying a password. Allowing that over basicHttp would be a significant security risk. Mar 27, 2013 at 0:38
  • That's very correct Frank. Cheers. On another note, I have managed to get an IronPython script using the "/CoreService2011.svc/wsHttp" endpoint, which I actually find more enjoyable than Powershell and will probably use in the future Apr 2, 2013 at 9:56
  • 1
    That's good to hear Gaizka. I guess some of us simply can't get used to that PowerShell syntax. I'm still a LINQPad guy myself. Using C# simply feels more natural to me: sdltridionworld.com/articles/sdltridion2011/… Apr 2, 2013 at 10:10
4

I do not know the root cause of it but to inform you that this error is not a new and does not entirely related with 2013 ONLY. I have received exactly same error couple of week back with Core Svc 2011. Scratched my head for almost a week to figure it out but in vain, tried all options suggested for this error on msdn and over the internet.....

and then I just restarted - created a new client (.net) with exactly same binding and end point configuration in app.config as web.config on the cms server for core svc (copied it from there indeed), double verify the authentication of sdl tridion site as well as for core svc application in iis, restarted all tridion svc, com+ and iis....and yuppiieee...it started working.

I am not sure if it will be of much help to you...but one thing should be useful..that this is not entirely related to 2013, but does exists in 2011.

3
+25

I don't think Impersonate was ever working/available on the basicHttp binding for the core service, so I would expect that to fail in both 2011 and 2013.

Your options to my knowledge are:

  1. netTcp

  2. wsHttp

If I gather correctly from your updates, you have netTcp working already, and are wondering how to do it using HTTP.

So for that I think you need the wsHttp binding:

<endpoint name="wsHttp_2012" address="http://localhost/webservices/CoreService2012.svc/wsHttp" binding="wsHttpBinding" bindingConfiguration="wsHttp" contract="Tridion.ContentManager.CoreService.Client.ISessionAwareCoreService">
  <identity>
    <dns value="localhost" />
  </identity>
</endpoint>

<wsHttpBinding>
  <binding name="wsHttp" transactionFlow="true" maxReceivedMessageSize="10485760">
    <readerQuotas maxStringContentLength="10485760" maxArrayLength="10485760" />
      <security mode="Message">
        <message clientCredentialType="Windows" />
      </security>
  </binding>
</wsHttpBinding>
1
  • Here's how the binding is created: $binding = New-Object System.ServiceModel.WSHttpBinding $binding.Security.Mode = [System.ServiceModel.SecurityMode]::Message $binding.Security.Transport.ClientCredentialType = [System.ServiceModel.HttpClientCredentialType]::Windows Which maps pretty closely on to your configuration Mar 27, 2013 at 20:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.