Windows Azure, SSL, Self-Signed Certificate and Annoying HTTPS Input Endpoint Does Not Contain Private Key Error
While I was trying out the Windows Azure features yesterday, I had a deployment problem. The case was to deploying SSL enabled web role. Let’s walk through the steps I have taken.
Since it was a try out, I decided to create a self-signed certificate instead of buying one. The case of how I created the self-signed certificate was fairly simple. I opened up the Visual Studio Command Prompt (2010) and cd to directory path where I would like to put the certificate file I was about to create. Then, I used the following makecert command line utility to create the certificate. Here is the code I used:
makecert -sky exchange -r -n "CN=TugberkUgurlu.Com" -pe -a sha1 -len 2048 -ss My "Azure.TugberkUgurlu.Com.cer"
I had my .cer file under c:\Azure\Certs directory. Also, I executed the following script on PowerShell console and I saw the certificate listed there.
In order to upload the certificate to windows azure, I needed to export the certificate from .cer file to .pfx. Here where things get messy. I used the followig powershell script to create one but I was about to realize that it was the wrong decision. We'll see why in a minute.
$c = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("c:\azure\certs\Azure.TugberkUgurlu.Com.cer") $bytes = $c.Export("Pfx","password") [System.IO.File]::WriteAllBytes("c:\azure\certs\Azure.TugberkUgurlu.Com.pfx", $bytes)
The next step was to deploy this .pfx file to Certificates store of my windows azure hosted service. In order to complate this challange, I went to Windows Azure portal, navigated to my hosted service. Right click on the blue Certificate folder (I think it is a folder icon but not sure exactly what it is) and click Add Certificate:
It poped up a dialog box for me to upload that certificate file. I completed the steps and there it was. I had the certificate deployed on my hosted service.
Finally, I was done setting things up and I can jump right to my application. Wait, I wasn't done yet complately! I had to set things up at the application level so that I could hook it up to that certificate I had just uploded.
At that stage, first thing I did was to grab the thumbprint of the certificate. I ran the following PowerShell command to grab the thumbprint of the certificate:
With that thumbprint, I went to my project and added the following code inside ServiceConfiguration.Clound.cscfg and ServiceConfiguration.Local.cscfg under Role node:
<Certificates> <Certificate name="Azure.TugberkUgurlu.Com" thumbprint="AAD5DDD0CA9B4D3CFEF1652130142020770B8BDF" thumbprintAlgorithm="sha1"/> </Certificates>
The ServiceDefinition.csdef file needed a little more touch than the configuration files. Here is the complate csdef file after the set-up:
<ServiceDefinition name="HttpsEnabledCloudProject" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition"> <WebRole name="MvcWebRole1" vmsize="Small"> <Sites> <Site name="Web"> <Bindings> <Binding name="Endpoint1" endpointName="Endpoint1" hostHeader="azure.tugberkugurlu.com" /> <Binding name="HttpsIn" endpointName="HttpsIn" hostHeader="azure.tugberkugurlu.com" /> </Bindings> </Site> </Sites> <Endpoints> <InputEndpoint name="Endpoint1" protocol="http" port="80" /> <InputEndpoint name="HttpsIn" protocol="https" port="443" certificate="Azure.TugberkUgurlu.Com" /> </Endpoints> <Imports> <Import moduleName="Diagnostics" /> </Imports> <Certificates> <Certificate name="Azure.TugberkUgurlu.Com" storeLocation="LocalMachine" storeName="My" /> </Certificates> </WebRole> </ServiceDefinition>
Everything looked right at that point but got an ugly error message telling me that my deployment had been failed:
HTTP Status Code: 400. Error Message: Certificate with thumbprint AAD5DDD0CA9B4D3CFEF1652130142020770B8BDF associated with HTTPS input endpoint HttpsIn does not contain private key
After a couple of searched on the internet, I ended up checking the private key of my certificate and here is the result:
That looked awkward and might be the problem. Then I grabed the certificate from the certificate store and check the private key. That was the evidence that it was the problem:
At that point, I created the .pfx file from the certificate in my certificate store with following code:
$cert = (get-item cert:\CurrentUser\My\AAD5DDD0CA9B4D3CFEF1652130142020770B8BDF) $bytes = $cert.Export("Pfx","password") [System.IO.File]::WriteAllBytes("c:\azure\certs\Azure.TugberkUgurlu.Com_2.pfx", $bytes)
At last, I deleted the certificate which was under my hosted service and reuploaded the new one I had just created.
Lastly, I ran the publish process again without changing anything inside my code, configuration or service definition files and I suceedded!
Here is the SSL enabled application running in the cloud:
Please comment if you have the same problem as me so that I won't feel lonely in this small World:)