April 3, 2013 at 4:05 PM

Some months ago, I was asked for an intervention regarding a SSL client certificate issue. There was a problem related to the setup of transport security (SSL) of a WCF service hosted in IIS 7.0, using client certificates that are mapped to a local account.  Let’s have a look.

 

The Setup

Server Setup

  • Wild card server certificate is installed in IIS (server level). Wild card is required, because we’re using multiple host names are configured.

          image

        image

 

  • The Certificate Authority is added to the Trusted Root Certification Authorities store (Local Machine)

        image

 

  • Website binding is configured to use https with the server certificate for SSL

        image

 

  • Website is configured to require SSL and to require client certificates

       image

 

  • Client certificate mapping is configured in order to map an individual client certificate to a specific Windows account. Configurable via this extension.

         image

       image

 

       This extension actually changes this configuration:

      image

 

  • An Allow authorization rule is configured for this Windows account

        image

 

  • Anonymous Authentication is enabled (Client Certificate is anonymous authentication)

        image

 

  • WCF service is configured for transport security

          image

 

Client Setup

  • The Certificate Authority is added to the Trusted Root Certification Authorities store (Local Machine)

           image

 

  • Client Certificate (containing private key) is added to the Personal certificate store (Local Machine).  This is required for the WCF client

          image

 

  • Client Certificate (containing private key) is added to the Personal certificate store (Current User).  This is required for browsing to the service via IE

         image

 

  • WCF Client is configured for transport security, providing Client Certificates:

          image

 

Problem Solving

The issue

When browsing to the service, for a particular web server, we’re not prompted to select a client certificate. Instead, we get this exception:

The page you are attempting to access requires your browser to have a Secure Sockets Layer (SSL) client certificate that the Web Server recognizes.

image

 

Troubleshooting

We configured another web server with exactly the same setup, which worked fine.  But still it didn’t work on that particular web server. Handy tools / commands during troubleshooting:

  • netsh http show sslcert
  • SSL Diagnostics

 

At the end, a warning in the System Event Log gave the solution. This entry is only written to the Event Log for the first call after the IIS service is restarted. That’s why we didn’t discover this Event Log warning earlier.

When asking for client authentication, this server sends a list of trusted certificate authorities to the client.  The client uses this list to choose a client certificate that is trusted by the server.  Currently, this server trusts so many certificate authorities that the list has grown too long.  This list has thus been truncated.

image

 

Root cause

During the handshake protocol for client certificate authorization, the server sends a list of Trusted Root Certification Authorities to the client.  The client will in this case only provide Client Certificates, issued by one of these Trusted Root Certification Authorities.  The problem was that the Trusted Root Certification Authorities list was too long on that particular server, so it was truncated before sent to the client.  Unluckily, our Root Certificate Authority was truncated from the list, so the handshake failed.

 

Solutions

There are two solutions to solve this issue:

  • The first solution is to clean up the Trusted Root Certification Authorities store (Local Machine) and remove all unnecessary certificates. Be aware that you don’t remove certificates that are required by Windows.

 

  • A second solution is to configure Schannel to no longer send the list of trusted root certification authorities during the TLS/SSL handshake process.  This can be done by adding this registry entry on the web server:

        HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL

        Value name: SendTrustedIssuerList
        Value type: REG_DWORD
        Value data: 0 (False)

 

Result

When browsing to the service, we’re now promoted for our Client Certificate. Now we can access the service:

         image

         image

Posted in: IIS | Security | SSL

Tags: , , ,


October 10, 2012 at 3:42 PM

On one of the projects we were doing, we needed to migrate the BizTalk 2006 R2 applications to BizTalk 2010.
This gave us the chance to change the running SOAP BizTalk services to WCF services. These services have more capabilities and are easier to configure.
We only had one restriction: the clients may not be forced to change. After some searching on the web, I found following post:

http://maximelabelle.wordpress.com/2010/08/12/creating-soap-compatible-biztalk-wcf-services/ and I like to share it with you.

First of all, I will explain how to expose a schema as a WCF Service;

Expose a Schema as a WCF Service

To create a WCF-service, use the BizTalk WCF Service Publishing Wizard. You can find it in the BizTalk Server 2010 folder at the Windows start menu.

clip_image001[5]

With this wizard you can set up the service endpoint.
You can choose between WCF-BasicHttp, WCF-WSHttp and WCF-CustomIsolated as a transport type and choose the application where you want to create the receive location in BizTalk.

clip_image002[2]

At the next step you get the choice to choose if you want to expose an orchestration or a schema as a WCF Service. In our case we will choose the schema choice.
The wizard gives you a tree of service methods, operations and request-response. Here you can add methods and one- or two-way operations. Define the schema type for your request and/or response from an assembly.

clip_image003[2]clip_image004[3]

clip_image005[2]clip_image006[2]

Fill in the target namespace of the WCF Service and choose the host and web directory where the service will be reachable.

The last step is a summary of the service you are going to create.... congratulations, you have created a WCF Service in BizTalk!

A new site is created in IIS and a receive location has been created for this service. The URI property refers to the address of the site in IIS.

Look also at the Receive Handler which is the BizTalkServerIsolatedHost. This means that this port is running under IIS.

clip_image007[2]

clip_image008[2]

Check if the receive location is started and if the Application pool of the site has the correct identity to work with BizTalk.

clip_image009[1]

If you try to browse to the site and receive a login error then you have to give the application pool the correct identity.

If after browsing to the site and you receive the following screen, you have created a WCF service with success.

clip_image010[1]

Change the Service to be able to communicate with the old SOAP-clients

First thing you need to do, is download the WSDL of the old SOAP Service and store it in the same folder of your SVC-file.

Open the WSDL and change the address location to the URI of the SVC-service.

When you look in the folder where the SVC-file is situated, there is also a web.config file of the service.

Load this web.config file in the WCF Service Configuration Editor for easy modifying.

clip_image011[1]

Go to the advanced tab and open the Service Behavior. Open the configuration and in the Service Metadata\ExternalMetadataLocation you have to add the path to the old WSDL. Save the config and close the configuration editor.

Now if you go to the service you will see that the URL of the WSDL has changed, also the WSDL itself now refers to the old one.

For the last step, you will need to change the Inbound BizTalk message body and the outbound WCF message Body.

The old ASMX message has one node more than a WCF envelope. You have to tell BizTalk were to get the find the message in the received envelope.

Open the settings of the receive location and click on configure, go to the message Tab. In the Inbound BizTalk message body check the path option and use the xpath '”/*/*” to go to the child node of the received message.

clip_image012

For the outboundWCF message body you need to wrap your message in an extra node because the client is demanding an extra Operation node as a wrapper. You also have to give this node the service namespace.

Restrictions, this pattern can only be used when you have a service that only has one operation due to the wrapper element you have to declare in the outbound WCF message body.

Hope this helps.
 - Robert Maes


May 22, 2012 at 4:05 PM

Lately, I had the task to create a generic WCF netTcp endpoint within BizTalk. The purpose was to create a single BizTalk ESB endpoint for each front-end application. BizTalk has the task to route and transform the SOAP requests to the corresponding back-end services.

 

I already had experience with hosting such an endpoint in-process (with the Custom adapter), but now it was required to host the endpoint in IIS (with the Custom-Isolated adapter). The reason for this decision is the fact that IIS, in combination with Windows Server AppFabric, adds extra tooling and manageability.

 

 

Enable Windows Activation Services

 

  • Add WAS as a Windows feature:

        clip_image002

 

  • Turn on WCF Non-HTTP Activation

        clip_image004

 

  • Start all WAS Windows Services. Change their startup type to Automatic. You can do this via Properties.

        clip_image006

 

Create IIS endpoint

  • Create a web service directory: C:\inetpub\wwwroot\BlogService

 

  • Open IIS Manager and convert the folder to an application

         clip_image008

 

  • Choose an application pool which is configured with the BizTalk isolated host user for .NET Framework 4.0

          clip_image010

 

  • Enable netTcp for the Default Web Site, via the Advanced Settings:

          clip_image012

 

  • Enable netTcp for the BlogService application, via the Advanced Settings:

        clip_image014

 

  • Add GenericEsbEndpoint.svc to the web service directory

        clip_image015

 

  • GenericEsbEndpoint.svc tells IIS to use the ServiceHostFactory of the BizTalk WCF adapter:

           <%@ ServiceHost Language="c#" Factory="Microsoft.BizTalk.Adapter.Wcf.Runtime.CustomWebServiceHostFactory, Microsoft.BizTalk.Adapter.Wcf.Runtime, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>

 

  • A web.config can be added, but all service behaviors (e.g. serviceDebug) can be configured on your BizTalk receive location too.

 

Create BizTalk receive location

  • Create a two-way receive port

        clip_image017

 

  • Create a two-way receive location and configure with the Custom-Isolated Adapter

        clip_image019

 

  • Configure the adapter URI with the format /<IIS Application Name>/<Service.svc>. Don’t use the scheme “net.tcp://” here!

        clip_image021

 

  • Configure the netTcp binding. Disable transport security (for performance reasons).

        clip_image023

 

  • Enable the BizTalk receive location

        clip_image025

 

  • Now you can additionally set up send ports and filters, to route the submitted SOAP request to the correct back-end services. Routing can be based on multiple properties, but the SOAP Action (WCF.Action) seems most suitable. Also transformations must be added in some cases.

 

Update the client binding

  • The client needs to be updated to send to the generic BizTalk endpoint, instead of directly to the back-end service. Update the client with the following address format: net.tcp://<machinename>:<tcpPortNumber>//<IIS Application Name>/<Service.svc>
<client>

<endpoint address="net.tcp://machineName:8888/BlogService/GenericEsbEndpoint.svc"

binding="netTcpBinding" bindingConfiguration="NetTcpBinding_ICoditService"

contract="PersonSvc.ICoditService" name="NetTcpBinding_ICoditService" />

</client>

 

  • The tcpPortNumber can be configured in the Site Bindings of the Default Web Site

        clip_image027

Posted in: BizTalk | IIS | SOA

Tags: