posted: August 09, 2010 | home | archive
My, that’s a long title….
On my current project we have developed a web-based API (e.g. sorta kinda RESTful) that allows remote applications to interface with our system. These remote applications currently include a Silverlight app and an iPhone app prototype.
Our web API is hosted at a secure HTTPS endpoint. This is crucial so that user credentials, which are required by our API, are not sent unencrypted across the internet. We could have chosen to require client applications to encrypt credentials before sending them to the API, but why not let SSL do that dirty work for you?
Our API is hosted in an Azure web role. When hosted at an HTTPS endpoint, the Azure web role must be configured for HTTPS and with the SSL certificate thumbprint before it is deployed to Windows Azure up in the cloud. This causes a problem for doing local development against the API when hosted in the Azure dev fabric: API calls will fail because the SSL certificate used does not match the localhost URL. When you browse a normal web site where the SSL certificate does not match the actual web site url, you get these certificate/identification warnings shown in browsers like Chrome and IE:


As a human, you can choose to bypass these warnings and let the web browser continue to render the site. However, with a web-based API your code won’t let you make that choice. Your code will fail, and rightfully so. We wouldn’t want our automated API to use a web site that was potentially spoofing us.
If you compile and deploy your Azure cloud package through a TFS build (or another build system), this presents a problem. You need a local Cloud Service project with no SSL certificate (or a different SSL certificate) configured for your developers to develop on, but then you need to deploy a Cloud Service that does have the SSL certificate configuration.
There are a couple ways to handle this. The first approach is the one I recommend. The second one I don’t recommend, but it could be useful in certain contexts.
1) Create Two Cloud Service Projects
This is the approach I recommend. It requires less trickery with TFS build tasks/scripts and relies more on permanently storing the HTTPS/Certificate data in the cloud service projects themselves. It’s just easier.
Basically, just create two Cloud Service projects in your solution that host the same project for the web role:

In one cloud service project, leave it with HTTP on port 80. With the second cloud project, add the HTTPS and Certificate configuration. You can do this by going to the Properties page for each web role in each cloud service project:


Now in your build/deploy automation you can just select which Cloud Service project and supporting files to use when calling cspack.exe. There. Done. Easy. Cake.
2) Modify the Azure Service Definition and Config at Build Time
At this time I do not recommend this approach as it just creates a lot of complexity in your build. I’m not even sure that this approach is worth writing about, but in some circumstances it may be appropriate. It’s also the first approach I tried in real life, and maybe after you read about it you can avoid the pain I went through.
The gist of this approach is to inject the HTTPS and SSL certificate configuration information into your Service Definition and Service Configuration files at build/deploy time. This will allow you to work with the Cloud Service package locally without HTTPS/SSL configuration, but deploy the package to Azure with the HTTPS/SSL configuration without additional Azure Cloud Service projects.
You’ll need to create custom tasks or scripts that will run during your build to make copies of the ServiceDefinition.csdef and ServiceConfiguration.cscfg files. You can even use new names for them. You’ll modify these new copies to include the HTTPS/SSL configuration. Point to your new copies when you run cspack.exe to create your cloud package.
In short, you’ll need to modify your ServiceDefinition.csdef file from this:
To this:
And modify your ServiceConfiguration.cscfg file from this:
To this (adding the Certificates element):
Obviously - use your own role and certificate names as well as your own real SSL thumbprint.
I recommend getting comfortable with these config settings and being able to read the XML before you start manipulating the files in a build task. You can warm up to the idea by manipulating these settings in the Properties of your Azure web role in Visual Studio. Visual Studio will modify your ServiceDefinition.csdef and ServiceConfiguration.cscfg files when you change these properties in Visual Studio:

Again, just use Visual Studio in a test project to warm up to the idea - you don’t want to embed the real SSL/HTTPS configuration into your local environment with this approach.
After you add custom scripts or tasks in your build to create the new Service Definition and Service Configuration, you can call cspack.exe, point to the right files, and generate an Azure package with the SSL/HTTPS configuration that you need.