How to Swap a WCF Service Between HTTP and HTTPS
We have recently had a number of customers who have installed irCatalog as an HTTP service who later wanted to make the eminently sensible choice to change the service to use HTTPS. Making this change is straightforward, but does require wading into the internals of WCF configuration. Although I will be describing how to accomplish this task in context of irServer or irCatalog, both services are, at the end of the day, just plain ol’ WCF services. This means that you can apply the same steps to almost any WCF services. Here are the steps you will follow:
- Obtain a SSL certificate
- Install the certificate on the IIS server hosting irCatalog or irServer
- Configure the site to require SSL
- Set host headers and bindings for SSL, including Server Name Identification if applicable
- Modify the irCatalog/irServer web.config to enable transport-level security for the service’s WCF bindings
In this blog post, we will only focus on the fifth step.
If you are not already familiar with the basic principles of SSL, TLS, and HTTPS, Troy Hunt wrote an in-depth article that covers the basics. Getting computer security right can be very tough, but if you are not even thinking about it, then it is downright impossible. This article assumes you have some familiarity with WCF, SSL, certificates, IIS, and related technologies. This article is NOT intended to be used when making decisions about your application’s security, just on how to enable SSL for your WCF-based services. Please do not forget that like any untrusted certificate, a self-signed certificate will cause applications like irAuthor to display security warnings – you can choose to either ignore the warnings, accept the certificate, or add the cert to your trusted store.
The first thing you will need when enabling SSL is a certificate. This can be self-signed or issued from a CA, whichever you end up using, you will need to install that certificate in IIS. The Server Certificates section of the IIS Admin tool is one place to manage this, but you can also import (or generate) a certificate using Powershell. This StackOverflow answer, as well as this one, explain how to do this in just a few lines of script. If you need help with these steps, an internet search for “IIS bind site SSL certificate” in your search engine of choice will likely yield some additional helpful links. Once you have created/imported your certificate, you will bind it to the IIS web site, which contains your irCatalog/irServer instance. Then you will be ready to finish the process by changing the web.config of the service.
Open the web.config of your irCatalog/irServer instance (default location is C:\Program Files (x86)\InRule\irServer\[Repository|RuleEngineService]\IisService\web.config), making sure you are running in an elevated session. Navigate to the system.serviceModel node, which is where you will be making the relevant changes.
Depending on whether you are looking at the web.config for irCatalog or irServer, the next steps will be similar, yet slightly different. irCatalog is the simplest, requiring only two changes. Look for the WSHttpBinding and change the security node’s mode attribute from “None” to “Transport”:
<bindings> <wsHttpBinding> <binding name="WSHttpBinding" maxReceivedMessageSize="50000000"> <readerQuotas maxStringContentLength="50000000" /> <security mode="Transport"> …
Next, we will want to make sure that we can access service metadata through https so we add a serviceMetadata entry to the repositoryServiceBehavior that specifies httpsGetEnabled=”True” and httpGetEnabled=”False”:
<behavior name="repositoryServiceBehavior"> <serviceDebug httpHelpPageEnabled="true" /> <serviceMetadata httpsGetEnabled="true" httpGetEnabled="false" /> </behavior>
Save the file and we are done with changing irCatalog! In the case of making this change to irServer, the steps are identical, but because the service has both SOAP and REST style endpoints, we need to repeat the process for each binding. In this, instance that means we need to change the securityMode to Transport in three different places. Note that the first security tag does not self-close like its’ brethren but it is an inconsequential inconsistency for anyone that doesn’t have an extreme case of OCD.
<wsHttpBinding> <binding name="WSHttpBinding_IRuleEngineService" maxReceivedMessageSize="2147483647"> <readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647" /> <security mode="Transport"></security> </binding> </wsHttpBinding> <webHttpBinding> <binding name="WebHttpBinding_IHttpRuleEngineService" maxReceivedMessageSize="2147483647"> <readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647" /> <security mode="Transport" /> </binding> </webHttpBinding> <basicHttpBinding> <binding name="BasicHttpBinding_IRuleEngineService" maxReceivedMessageSize="2147483647"> <readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647" /> <security mode="Transport" /> </binding> </basicHttpBinding>
If you guessed that our next, and final, task is to modify the service’s behavior to enable httpsGet of serviceMetadata, you win a gold star. Once you have saved the web.config it is not a bad idea to restart the site via an iisreset or similar command – be careful if you are performing this in an active, “live” environment!
<behavior name="Behavior_IRuleEngineService"> <serviceDebug httpHelpPageEnabled="true" /> <serviceMetadata httpsGetEnabled="true" httpGetEnabled="false" /> </behavior> <behavior name="Behavior_IHttpRuleEngineService"> <serviceDebug httpHelpPageEnabled="true" /> <serviceMetadata httpsGetEnabled="true" httpGetEnabled="false" /> </behavior>
So that is all there is to changing a WCF service from using HTTP to HTTPS. Not too bad, eh? It goes without saying that changing from HTTPS back to HTTP is a matter of performing the outlined steps in reverse. Hopefully this article can save you some time managing your InRule environments and allow you to spend more time writing rules. Happy InRule-ing!