I run a multi-tenant SaaS product called OnCall where each of the tenants get a unique sub-domain. The front-facing parts of the application is run on Azure as a web role which means I needed to install a wildcard certificate for the web role to provide SSL for the tenants.
To achieve that I went through the following steps
- Get a wildcard certificate
- Upload certificate to Azure
- Configure the web role
1. Get a wildcard certificate
Choosing a certificate provider
The first thing you need to do is go out and buy a wildcard certificate. You can choose any provider you prefer, but if you haven't got any specific preference you could go and check out Namecheap who is a reseller of certificates. They offer wildcard certificates for around $100/year.
Creating a certificate signing request
When you buy a certificate you always start by creating a Certificate Signing Request (or CSR). Usually when securing a website hosted on an IIS server, you will generate the CSR using the IIS Manager tool.
But since our focus is on a web role this is not straight forward. You could enable remote desktop on the web role, or you could use your local IIS installation (if you have one). But instead I suggest taking a look at this great little tool from DigiCert
You generate your CSR in a couple of steps
- Choose the SSL tab
- Click "Generate CSR"
- Generate the CSR by
a. Filling in "Common Name", which in this case is *.your-domain.tld
b. Filling in your organization info (it should match the WHOIS record for your domain
Save your CSR and upload it to your certificate provider as part of the ordering process.
Preparing your certificate for Azure import
When you have successfully ordered and received a certificate from your provider you can go ahead and import that back into to the DigiCert tool.
After doing this the tool allows you to export the certificate as PFX-file that you can import into Azure from the Azure Management Portal.
As part of the PFX export you will be asked to provide a password. Make sure you use a password you remember, as this is required to import it into Azure.
2. Upload certificate to Azure
OK. Now we have obtained a wildcard certificate. Before we start configuring anything (and before we forget that password we used in the last step) we should upload the certificate to Azure.
- Open Azure Management Portal
- Find your web role
- Navigate to "Certificates"
- Upload your PFX-file
After uploading it, the certificate and all included intermediates will show up in the list. Locate the one with your domain name in it and copy the thumbprint, as we will need that in the next step.
3. Configure your web role
With the certificate ready to go in Azure we need to configure the web role to accept HTTPS connections. We will be making changes to:
- The ServiceConfiguration.cscfg file
- The ServiceDefinition.csdef file
Add the certificate to ServiceConfiguration.cscfg file
I am setting up the certificate for the production environment, which in my case means changing the ServiceConfiguration.Production.cscfg file.
<Role name="Awesome.Web.App"> <Instances count="1" /> <ConfigurationSettings> .. </ConfigurationSettings> <Certificates> <Certificate name="SSL" thumbprint="7335E9DFD5F7C865A7EE373AE5B5C3CE8EDD229D" thumbprintAlgorithm="sha1" /> </Certificates> </Role>
This should look familiar. I have simplified it a bit, but what you need to do is to add a new section "Certificates" and provide an entry for your certificate. Choose a name and leave the thumbprintAlgorithm as "sha1". The thumbprint algorithm has nothing to do with the certificate hashing algorithm.
Paste in the thumbprint you got from Azure after uploading your certificate.
Update the ServiceDefinition.csdef file
There are couple of things of things you need to do here.
- Add the certificate
- Add new endpoint
- Add new binding
Take a look at the following configuration, and we will go through each of the three steps in detail.
<WebRole name="Awesome.Web.App" vmsize="Small"> <Sites> <Site name="Web"> <Bindings> <Binding name="HttpIn" endpointName="HttpIn" /> <Binding name="HttpsIn" endpointName="HttpsIn" /> </Bindings> </Site> </Sites> <Endpoints> <InputEndpoint name="HttpIn" protocol="http" port="80" /> <InputEndpoint name="HttpsIn" protocol="https" port="443" certificate="SSL" /> </Endpoints> <ConfigurationSettings> </ConfigurationSettings> <Certificates> <Certificate name="SSL" storeLocation="LocalMachine" storeName="My" /> </Certificates> </WebRole>
Add the certificate
Create a new section called "Certificates", add a new "Certificate" entry to it, using the same name you used in your service configuration, in this case SSL.
Add new endpoint
Create a new HTTPS endpoint using the name of the certificate in the "certificate"-attribute.
Add new binding
Create a new binding, using the endpointName of the newly added HTTPS endpoint.
Added bonus: Forcing HTTPS only
If you want to force your users to use HTTPS rather than HTTP, and your application is an MVC app, you could consider adding this to Application_Start().
This will add the [RequireHttps]-attribute to all actions, basically redirecting any user arriving on a HTTP connection to HTTPS.
This will also force HTTPS when running the application locally, so if that is a problem, you should implement a check for local adresses, debugging flags or similar.
And that is about it. When you deploy your application to Azure, you should see your multi-tenant sub-domains protected by your wildcard certificate.