In a recent project at Tekaris I had to fetch data from an external webservice. The service was only accessible with a certificate. No credential based authentication was possible. So the provider sent me the required certificate which I imported to my local developer machine. Everything worked as excepected as long as it came to deployment.
The following environment is given:
- Visual Studio 2013
- Windows Azure Cloud Service
- Windows Azure Worker Role
In order to deploy the certificate the following steps are necessary:
- Upload the certificate to Azure. It has to be a .pfx or .cer file containing the private key and all other certificates in the certificate path
- Configure the certificates in the Worker Role project of your Cloud Service in Visual Studio
The upload of the certificate is quite simple. Connect to the Azure Poral, select your Cloud Service and switch to the Certificates tab. There you can easily upload the .pfx or .cer file. You need the password that was used when exporting the certificate. After the upload you can see all certificates within the certificate path and their thumbprint.
To configure which certificates are deployed to the target machine open the properties of the Worker Role in your cloud project (not of the Worker Role project itself). In the Certificates section add the required certificates. In this post I´ve described how to get the thumbprint of a certificate.
In my case I had the following certificate path:
When I was configuring the certificates in the Worker Role project I was not able to set Root as the store for the root certificate. I got the following errormessage:
Installing a certificate to the LocalMachine/Root store is not supported.
In order to get the deployment package built I had to change from Root to Trust. That meant that Azure deployed the Root Certificate into the Enterprise Trust Store on the target machine which caused a broken certificate path.
So after the deployment I connected to the target machine via RDP and moved the Root Certificate manually to the correct store. But this step would be necessary every time I deploy the package into a new environment or when the Azure Scaling framework would increase the number of machines. Not a feasible solution. That must happen automatically.
I decided to write some logic that checks on start of the Worker Role whether the certificate is in the correct store and moves it there if necessary. The following code shows only an example how to move a certificate from a defined source to a defined target store by its friendly name. My productive solution is a lot more flexible and configurable 😉
public void EnsureCorrectRootCertificateStore()
var certificateFriendlyName = "Friendly_Name_Of_The_Certificate";
var trustedRootAuthoritiesStore = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
// Check whether the certificate is already in the correct store
foreach (var rootCertificates in trustedRootAuthoritiesStore.Certificates)
if (rootCertificates.FriendlyName == certificateFriendlyName)
var enterpriseTrustStore = new X509Store("Trust", StoreLocation.LocalMachine);
// Search for the certificate in the "Enterprise Trust" store
foreach (var cert in enterpriseTrustStore.Certificates)
if (cert.FriendlyName != certificateFriendlyName)
// Remove it from "Enterprise Trust"
// Add it to "Trusted Root Authorities"
One additional thing is necessary to get the code working. The Worker Role must run in elevated mode. Otherwise the access to the Trusted Root Authorities Store would be denied.
Open the ServiceDefinition.csdef file of your Cloud project. Inside the WorkerRole section add an element with the name “Runtime” and the attribute “executionContext” with “elevated” as value. Example:
<WorkerRole name="MyWorkerRole" vmsize="ExtraSmall">
<Import moduleName="Diagnostics" />
<Certificate name="my.certificate" storeLocation="LocalMachine" storeName="My" />
<Certificate name="Intermediate" storeLocation="LocalMachine" storeName="CA" />
<Certificate name="Root" storeLocation="LocalMachine" storeName="Trust" />
So that´s it. It took me some time to get all these pieces together and hopefully these lines would prevent you from having the same “nice” experience 🙂