I have a WSE 3.0 based web service running in Windows Server 2003 under IIS 6.0. I want the web service process to impersonate the client user that sends the web service request, however the service is not impersonating the client.
The web application has its own app pool, which is currently set to run under the Network Service identity. The Windows Server 2003 machine account has been enabled for delegation in Active Directory (at least according to my IT guy). The service WSE policy (in wse3policyCache.config) looks like this:
<policy name="GeneratedServicesPolicy">
<kerberosSecurity establishSecurityContext="false" renewExpiredSecurityContext="true" requireSignatureConfirmation="false" messageProtectionOrder="SignBeforeEncrypt" requireDerivedKeys="true" ttlInSeconds="300">
<protection>
<request signatureOptions="IncludeAddressing, IncludeTimestamp, IncludeSoapBody" encryptBody="false" />
<response signatureOptions="IncludeAddressing, IncludeTimestamp, IncludeSoapBody" encryptBody="false" />
<fault signatureOptions="IncludeAddressing, IncludeTimestamp, IncludeSoapBody" encryptBody="false" />
</protection>
</kerberosSecurity>
<requireActionHeader />
</policy>
The service has the following entries (among others) in its web.config:
<identity impersonate="false"/>
<authentication mode="Windows"/>
Anonymous access is enabled for the application (this is required since transport-level security is not used by the service, message-leve is). The machine account has the following SPN's registered:
HOST/RD360-2
HOST/rd360-2.mycompany.com
The client has the following in its wse3policyCache.config:
<policy name="KerbClient">
<kerberosSecurity establishSecurityContext="false" renewExpiredSecurityContext="true" requireSignatureConfirmation="false" messageProtectionOrder="SignBeforeEncrypt" requireDerivedKeys="true" ttlInSeconds="300">
<token>
<kerberos targetPrincipal="HOST/rd360-2.mycompany.com" impersonationLevel="Impersonation" />
</token>
<protection>
<request signatureOptions="IncludeAddressing, IncludeTimestamp, IncludeSoapBody" encryptBody="false" />
<response signatureOptions="IncludeAddressing, IncludeTimestamp, IncludeSoapBody" encryptBody="false" />
<fault signatureOptions="IncludeAddressing, IncludeTimestamp, IncludeSoapBody" encryptBody="false" />
</protection>
</kerberosSecurity>
<requireActionHeader />
</policy>
The client code looks like this:
static void Main(string[] args)
{
AddFloatsWSWse client = new AddFloatsWSWse();
client.SetPolicy("KerbClient");
double result = client.AddFloats(2.3, 3.2);
Console.WriteLine("Result was: '" + result + "'");
}
The service is not impersonating my client identity, though. I am using log4net in the service, and when I ask it to print out the %username
into the ASP.NET trace log, it is always NT AUTHORITY\NETWORK SERVICE
and not the client user id. Is there anything I'm doing wrong? Is there somewhere I can look to see if WSE is even trying to perform the impersonation and failing? I do see the following entries in my event log (MYDOMAIN and MYUSER are obscured here):
Event Type: Success Audit
Event Source: Security
Event Category: Privilege Use
Event ID: 576
Date: 12/9/2009
Time: 11:07:16 AM
User: MYDOMAIN\MYUSER
Computer: RD360-2
Description:
Special privileges assigned to new logon:
User Name: MYUSER
Domain: MYDOMAIN
Logon ID: (0x0,0x4B410AE)
Privileges: SeSecurityPrivilege
SeBackupPrivilege
SeRestorePrivilege
SeTakeOwnershipPrivilege
SeDebugPrivilege
SeSystemEnvironmentPrivilege
SeLoadDriverPrivilege
SeImpersonatePrivilege
----------------------------------------------------------------------------------
Event Type: Success Audit
Event Source: Security
Event Category: Logon/Logoff
Event ID: 540
Date: 12/9/2009
Time: 11:07:16 AM
User: MYDOMAIN\MYUSER
Computer: RD360-2
Description:
Successful Network Logon:
User Name: MYUSER
Domain: MYDOMAIN
Logon ID: (0x0,0x4B410AE)
Logon Type: 3
Logon Process: Kerberos
Authentication Package: Kerberos
Workstation Name:
Logon GUID: {OBFUSCATED}
Caller User Name: -
Caller Domain: -
Caller Logon ID: -
Caller Process ID: -
Transited Services: -
Source Network Address: -
Source Port: -
And in my WSE trace file I do see:
<processingStep description="Entering SOAP filter Microsoft.Web.Services3.Design.RequireSoapHeaderAssertion+RequireSoapHeaderFilter" />
<processingStep description="Exited SOAP filter Microsoft.Web.Services3.Design.RequireSoapHeaderAssertion+RequireSoapHeaderFilter" />
<processingStep description="Entering SOAP filter Microsoft.Web.Services3.Design.KerberosAssertion+ServiceInputFilter" />
<processingStep description="Exited SOAP filter Microsoft.Web.Services3.Design.KerberosAssertion+ServiceInputFilter" />
so at least I know the Kerberos extensions are processing my Kerberos headers. Thanks in advance for any help or hints!
Edit: My webservice then uses a proprietary client communication library to call into another server using SSPI/IWA (let's call this third server a foo server). I want it to use the client's identity when it makes this second call into the foo server. This means that this client communication library calls AcquireCredentialsHandle
and InitializeSecurityContext
using the SPN of the foo server and a different service. In this particular case, the foo server is actually running on the same machine as the WSE web service (so it's using the SPN mycompany/rd260-2
). Since this second hop is to the same machine, I would expect this to use NTLM, but it still should impersonate my web service client's user identity, shouldn't it? In the logs of the foo server, I see that it accepts the connection, uses the IWA security context provided and tells me that based on this security context, the connecting user is rd36-2$
which is the machine account since the WSE web service is running in IIS under the Network Service identity (which is in turn associated to the machine account). In the logs of the foo server, after it receives the IWA security context, I ultimately want to see the identity of the user who submitted the web service request. Would it be useful to move the foo server to a different machine to see if that has some bearing on this?