Recently I was working for the customer on the proof of concept for N-tier application where the client was using IE to authenticate itself against the web tier that talks to the app tier which talks to SQL Server. It sounds like an relatively easy task even in .NET 1.1, but the web tier had to be load balanced and the app tier had to be load balanced and both tiers are running on physically separate boxes. Plus the original caller identity had to flow from IE to IIS and to the app server for authorization purposes. All involved parties are configured in Windows domain with Active Directory. The restriction is that you cannot run IIS as the hosting environment on the app tier for security reasons (I know it may not be reasonable, but this is the mandatory infrastructure requirement). The oviy nature aous choices prior to .NET 3.0 were COM+/Enterpsie Services, NET Remoting or ASMX web services. NET Remoting is insecure by nature and is not a good migration path to future communication platform, ASMX service cannot run w/o IIS.

So COM+/Enterpise Services had to examine. It works as expected with one caveat: you need to setup the Kerberos delegation to allow the caller identity to flow from the IE to IIS to the middle tier. Kerberos is required to authenticate services (IIS and app tier) and it is the prerequisite for the delegation. This solution works pretty well with single IIS and app tier servers.

If you add the load balancer to the web tier (hardware load balancer or NLB) you can still make the Kerberos working (see http://www.microsoft.com/technet/prodtechnol/windowsserver2003/technologies/security/kerbnlb.mspx). The whole trick here is that you are registering the service principal name (SPN) for the domain user account under with the IIS application poll runs for all IIS services (e.g. setspn –a http/<serverN> domain\user) and the load balancer name (e.g. setspn –a http/<nlb> domain\user). It means that the IE client hits the load balancer <nlb> and receives the response from one of the <serverX>. There are special requirements how to enable IIS to use Kerberos authentication (see http://support.microsoft.com/?id=215383).

If you add the load balancer to the app tier (again it can be a hardware or software solution), the Kerberos delegation stops working with COM+ being unable to do mutual authentication against the load balancer name. The problem is that most COM+-related services (e.g. remote procedure call) are running under the NT Authority\Local System account which maps to the Domain Computer account for all external connection. the Making the same configuration for NLB-Kerberos, but for COM+ proved to be impossible as there is no way to use the custom domain user account for the COM+-related services. Yes, you have already heard it: DO not change the accounts under which the RPCSS et al runs as it will break the Windows OS. So if you are stuck with COM+-only, your only way to resolve the issue is to configure the COM+ proxies at the web tier servers to use the individual app tier servers (NOT the app tier <nlb>). You have good utilization of the web tier resources, but somewhat questionable utilization of app tier resources.

Here is when WCF comes handy. WCF offers more flexibility for hosting the services:

·        Self-hosting (e.g. WinForms, console app)

·        IIS 5.0/6.0 or WAS/IIS 7.0 in Vista

·        Windows/NT Service

Using console application is not a good choice for the app tier. Running IIS 5.0/6.0 is not possible because of the infrastructure constraints. Windows Activation Services (WAS) are coming only with Vista and we cannot wait for it. So the natural choice was left for Windows Service. It offers automatic startup and RUNNING UNDER THE SPECIAL DOMAIN ACCOUNT. All you have to do is to start the WCF service inside the Windows/NT Service, configure it to use one the bindings and enable impersonation on the client or service WCF configuration. Below is the detailed explanation how it can be done:

The custom NT Service class:

    public class Service : ServiceBase

    {

        private ServiceHost serviceHost = null;

 

        protected override void OnStart(string[] args)

        {

            if (serviceHost != null)

            {

                serviceHost.Close();

            }

 

            serviceHost = new ServiceHost(typeof(WCFService));

 

            serviceHost.Open();

        }

 

        protected override void OnStop()

        {

            if (serviceHost != null)

            {

                serviceHost.Close();

                serviceHost = null;

            }

        }

      }

The application configuration file is not different from the one that you can find the SDK samples:

 

<system.serviceModel>

    <bindings>

      <netTcpBinding>

        <binding name="tcpBinding" />

      </netTcpBinding>

    </bindings>

    <services>

      <service behaviorConfiguration="MyServiceBehavior" name="Esps.BusinessObjects.RegionManager">

        <endpoint address="mex" binding="mexTcpBinding" bindingConfiguration=""

          name="Mex" contract="IMetadataExchange" />

        <endpoint binding="netTcpBinding" bindingConfiguration="tcpBinding"

          name="Tcp" contract="IWCFService" />

        <host>

          <baseAddresses>

               <add baseAddress="net.tcp://localhost:8001/service" />

          </baseAddresses>

        </host>

      </service>

    </services>

 

    <!--For debugging purposes set the includeExceptionDetailInFaults attribute to true-->

    <behaviors>

      <serviceBehaviors>

        <behavior name="MyServiceBehavior">

          <serviceMetadata httpGetEnabled="true" />

          <serviceDebug httpsHelpPageEnabled="false" includeExceptionDetailInFaults="true" />

        </behavior>

      </serviceBehaviors>

    </behaviors>

  </system.serviceModel>

 

When you install the Windows Service, you need to set the account under which it runs to the selected domain user account (e.g. Domain\MyServiceAccount).

 

The WCF client configuration which you setup at each web application will need to contain the following information:

 

<bindings>

   <netTcpBinding>

    <binding name="tcpBinding" />

   </netTcpBinding>

  </bindings>

            <client>

   <endpoint address="net.tcp://nlbFQDN:8001/service" binding="netTcpBinding"

    bindingConfiguration="tcpBinding" contract="IRegionManager"

    name="IRegionManager">

     <identity>

       <servicePrincipalName value="MYSERVICE/NLB"/>

     </identity>

   </endpoint>

 

What is servicePrincipalName and what is MYSERVICE/NLB? See the infrastructure setup below:

1)    Add Domain\MyServiceAccount to the Active Directory

2)    Mark this account as trusted for delegation (see Account tab or Delegation tab in the AD User configuration)

3)    Add the SPN for the WCF hosting service for each machine where you are installing the service:

Setspn –a myservice/<serverN>:8001 Domain\MyServiceAccount

Setspn –a myservice/<serverN-FQDN>:8001 Domain\MyServiceAccount

4)    Add the SPN for WCF hosting service for the app tier NLB name:

Setspn –a myservice/<nlb>:8001 Domain\MyServiceAccount

Setspn –a myservice/<nlb-FQDN>:8001 Domain\MyServiceAccount

5)    Use the service and the app tier.

 

Note 1: SPN is built in the form servicename/<servername>:<portnumber>. <servicename> can be any string that uniquely identifies your service in your domain except for the well-known SPNs (host, dcom, http etc.). If you register SPN using the well known SPN, you will end up with duplicate SPN which breaks Kerberos authentication. Finding the duplicates can be done by searching the Active Directory. <portnumber> is the port number that your binding is configured for.

 

Note 2: In the previous examples I used FQDN as acronym for “Fully-Qualified Domain Name”. It is important to use it instead of the short NETBIOS name to make Kerberos working.

 

Note 3: IE client must be configured to use Integrated Security and the domain name where the web tier load balancer is located must be added to the Local Intranet or Trusted Sites section. The simple ASP page can be used to verify the protocol used to authenticate the IE client against IIS (see the listing below). If the Kerberos authentication chain is broken between IE and IIS, it defaults to NTLM which cannot be used to hop more than one time and disables the services mutual authentication.

 

Note 4: That said, there are only 2 products out of the box that can do Kerberos delegation easily and work in NLB environment. They are IIS and SQL Server. But you can easily make your application working in the same manner using WCF and Windows Service. Of course, if you can host the WCF service in IIS, this is also achieved easily and you gives you additional benefits of automatic activation and monitoring.

 

Note 5: In Windows 2003 functional level you can configure the Kerberos to work only with specific services. This is called Kerberos constrained delegation. See details here: http://technet2.microsoft.com/WindowsServer/en/library/c312ba01-318f-46ca-990e-a597f3c294eb1033.mspx?mfr=true.