BizTalk WCF Receive Location Configuration Error: The SSL settings for the service ‘None’ does not match those of the IIS ‘Ssl, SslRequireCert, Ssl128’
A BizTalk WCF endpoint is exposed with security enabled: SSL with a client certificate is required (so mutual, 2-way client and server authentication is configured).
BizTalk (2009) receive location is configured as follows:
(Incidently, the following command can be run in a Windows batch file to configure SSL for a IIS virtual directory:
%windir%\system32\inetsrv\appcmd.exe set config “Default Web Site/ServiceName” -commitPath:APPHOST -section:access -sslFlags:Ssl,Ssl128,SslRequireCert )
Error Message and Analysis
Clients were unable to connect to the service and the following exception message was written to the Application event log on the hosting BizTalk server:
Exception: System.ServiceModel.ServiceActivationException: The service ‘ServiceName.svc’ cannot be activated due to an exception during compilation. The exception message is: The SSL settings for the service ‘None’ does not match those of the IIS ‘Ssl, SslRequireCert, Ssl128’.. —> System.NotSupportedException: The SSL settings for the service ‘None’ does not match those of the IIS ‘Ssl, SslRequireCert, Ssl128’.
So this is an IIS configuration issue. The service is exposing some endpoint that is unsecured (the SSL setting for this endpoint is ‘None’, as mentioned in the error message), which doesn’t match the actual SSL settings configured: ‘Ssl, SslRequireCert, Ssl128’ (i.e. SSL with minimum 128-bit keys and client certificate required).
In this case, the endpoint not matching the SSL settings is the mex endpoint (i.e. the service WSDL).
Ensure that ALL mex endpoints are disabled, by commenting out the following mex binding configuration in the service Web.config file:
The <system.serviceModel> section specifies Windows Communication Foundation (WCF) configuration.
<serviceDebug httpHelpPageEnabled=”false” httpsHelpPageEnabled=”false” includeExceptionDetailInFaults=”false” />
<serviceMetadata httpGetEnabled=”false” httpsGetEnabled=”true” />
<!– Note: the service name must match the configuration name for the service implementation. –>
<!– Comment out mex endpoints if client auth enabled using certificates –>
<service name=”Microsoft.BizTalk.Adapter.Wcf.Runtime.BizTalkServiceInstance” behaviorConfiguration=”ServiceBehaviorConfiguration”>
<!–<endpoint name=”HttpMexEndpoint” address=”mex” binding=”mexHttpBinding” bindingConfiguration=”” contract=”IMetadataExchange” />–>
<!–<endpoint name=”HttpsMexEndpoint” address=”mex” binding=”mexHttpsBinding” bindingConfiguration=”” contract=”IMetadataExchange” />–>
I restarted IIS and the service could then be compiled and worked as expected.
Dynamic send ports allow adapter properties to be set at runtime (and also to select the adapter to be used). In my particular BizTalk 2009 scenario, I was creating a WCF dynamic send port to call a service endpoint URI only known at runtime, specified by the client (my orchestration is designed to be a generic message broker).
My first dislike was WCF configuration had to be defined programmatically in my orchestration. Sure, I was storing the properties in a custom SSO application so they weren’t hardcoded, but the BizTalk admin console provides a standard mechanism to configure WCF properties and it made sense to use it. Thinking of the BizTalk admins, I didn’t like the idea of hiding configuration away and then in a non standard way: it makes troubleshooting more difficult.
Secondly: performance. A few of my colleagues and sources on the web advised of poor performance using dynamic send ports for these reasons:
1. A dynamic send port is created each time it is used and in the case of WCF, for instance, the channel stack is created each time. This can have a significant performance hit. Further information about this is available here.
2. Only the default handler for each transport can be used which is a potential performance bottleneck if the host instance used by the default handler hasn’t been optimized for send operations. This limitation is also a recipe for inconsistent configuration (for example, if a design decision has been made to use a particular host for particular functions, this will not enforceable) and also it isn’t obvious to the BizTalk admins, what handler is used for a particular port. (Note that this limitation has been removed in BizTalk 2013 where it is now possible to choose a host instance for a dynamic send port, other than being stuck with just the default handler).
So I decided to use a static send port and override the “dummy” URI in my send port with the actual URI provided by the client… I did this as follows:
1. In my orchestration, in a Construct Message shape, I assigned to my own custom context properties, values that would later to be used to populate the BTS.OutboundTransportLocation and WCF.Action properties (these specify the endpoint URI and SOAP operation used by the WCF adapter, respectively). I did this instead of assigning directly to the “out of the box” properties since both were later overwritten on receipt of the message by the send port.
2. Using a custom pipeline component, I then promoted properties BTS.IsDynamicSend, BTS.OutboundTransportLocation and WCF.Action in a send pipeline assigned to the send port, populating BTS.OutboundTransportLocation and WCF.Action using the values assigned to my custom context properties like this:
inmsg.Context.Promote(“IsDynamicSend”, “http://schemas.microsoft.com/BizTalk/2003/system-properties”, true); // Set this to prevent URL caching.
inmsg.Context.Promote(“OutboundTransportLocation”, “http://schemas.microsoft.com/BizTalk/2003/system-properties”, endpointURL);
inmsg.Context.Promote(“Action”, “http://schemas.microsoft.com/BizTalk/2006/01/Adapters/WCF-properties”, operationName);
Note that BTS.IsDynamicSend has been set to “true”. As mentioned on MSDN here, this causes the send adapter to not used cached configuration, but to read configuration from the message context each time the send port is used. If BTS.IsDynamicSend was not set for example, then the cached endpoint URI would be used over the endpoint URI actually stamped on the message which was not what I wanted, since it’s possible that the endpoint may change between calls.
Performance: running my SOAPUI load tests, the response times of my web service were the same after changing to use a static port over a dynamic port. I’m using the WCF-Custom adapter with wsHttpBinding in my static send port. The response time of my web service was already acceptable to my client and my main motivation in using a static send port was better configuration options using the BizTalk admin console (rather than storing configuration in a custom SSO application). However better perfomance would have been nice! If I have time, I may investigate this further across the different adapters.