For enterprises, power users and people who simply don’t like the Azure administration portal but do use Windows Azure as an deployment option for their applications or services it may be desirable to integrate deployment and administration tasks into automatic processes and/or customized tools. To support that Microsoft provides a REST based Service Management API. This API is quite comprehensive and allows you to view and alter your deployments, services and storage accounts. In order to secure access to those resources via the API mutual authentication of certificate over a SSL connection is required. In addition also the Subscription-ID of your account is needed as part of the rest URLs to correctly address your resources. While this is by no means a security feature it is recommended to keep this ID a secret, though. But back to the Certificates now. In order to use the service API you need to have a certificate that you associate with your service API. You can do that by using the developer portal and go to the “Account” page and then use the link “Manage My API Certificates”. Then you are able on import A DER encoded binary representation of your certificate (use certmgr.msc on Windows to do so).

In order to get a certificate for use with the Windows Azure Service Management API there are several possibilities:

  1. Create one using the makecert.exe tool which comes with the Windows SDK and also with Visual Studio. How to create a suitable self signed certificate with makecert.exe refer to this blog post
  2. Create a self signed certificate using the IIS Management console. Refer to this Technet article to see how this can be done.
  3. Get a certificate from a Certificate Authority (CA) such as Verisign, GoDaddy, CACert.org, etc.

It is to note that:

  1. The certificate doesn’t need to be a server certificate (enhanced key usage: server authentication). A client certificate is necessary (and probably also easier/cheaper to get from your CA). However please be aware that this cannot be used as a SSL certificate for one of your services (which wouldn’t probably be a good idea anyway)
  2. The certificate needs to have at least a 2048 bit key

Refer to the API documentation for further information.

No you might ask why do I write all this when this is mostly already documented. Because I got my certificate via the automated process of CAcert.org. And in my first try I run into an error that I was not able to get my Service Management API requests authenticated. The service always returned:

Error 403 (Forbidden): The HTTP request was forbidden with client authentication scheme 'Anonymous'

I didn’t really understand why this was happening as I was creating the certificate in my code using one of the above mentioned DER encoded binary .cer files which I exported from the management console. Here is the code which is really not that complicated.

 

  1. try
  2. {
  3.     X509Certificate cert = X509Certificate.CreateFromCertFile("AzureCert.cer");
  4.     HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://management.core.windows.net/<subscription-id>/services/storageservices");
  5.     req.ClientCertificates.Add(cert);
  6.     req.UserAgent = "Azure Cloud Management Studio";
  7.     req.Method = "GET";
  8.     req.ProtocolVersion = HttpVersion.Version11;
  9.     req.Headers.Add("x-ms-version", "2009-10-01");
  10.     req.ContentType = "text/xml";
  11.     HttpWebResponse response = (HttpWebResponse)req.GetResponse();
  12.     ...
  13. }
  14. catch (Exception ex)
  15. {
  16.     ...
  17. }

After a while of investigating I realized that as I created the .cer file from a certificate string shown outlined in the picture below.

CAcert install certificate page

However I did not realize that I’m then missing the private key generation process that included by clicking on the install button and uses ActiveX in Internet Explorer.

“Your private key is generated by your browser, *IN* your browser when you request a new cert from CAcert. That way CAcert never has your private key in its possession. The implication for you is that you must be on the same machine using the same browser that you used to request the cert initially, when needing to access your private key. So don't forget if it was your "work" machine vs. your "home" machine.”

Unfortunately I couldn’t get that to work with IE8 and Windows 7 what brought me to use the certificate string in the first place. But if you walk down this road and copy that string into a text file, change the file extension to .cer and then install the certificate you will not have a private key associated with this certificate and that’s why the request is failing. In order to have the requests working you need to meet two prerequisites for your certificate:

  1. The certificate needs to be installed in the certificate store of the client machine from where you send the requests to the Service Management API.
  2. The certificate must have an associated private key.

For me this meant:

  1. Use Windows 7 XP Mode and IE6 ;) to issue a new certificate request to CACert.org
  2. Install the certificate from the CAcert.org website using the same browser in the same XP Mode instance
  3. Export the certificate as a Personal Information Exchange (PKCS#12) file including the private key (note that such file have an .pfx file extension)
  4. Import the the certificate on the Windows 7 system used to work with the Service Management API
  5. Make sure that the private key is available

    Ensure there is a private key
  6. Export the certificate again as a DER encoded binary .cer file (this time make sure that the private key is not exported 1. because you don’t need it on the Azure side and 2. you wouldn’t be able to create a .cer file)

    Do not export the private key Export as DER encoded binary
  7. Import the .cer file with the Azure Management Console

    Azure Devloper Portal 

After all those steps I was able to issue successful requests with my own code as well as available tools to interact with the Windows Azure Service Management API such as csmanage.exe or the PowerShell Windows Azure Service Management CmdLets. However just to note it again this only works because the certificate is actually also installed in the certificate store where the .Net Cryptographic API does a lookup of the certificate and its corresponding private key. You can verify this if you import the certificate in step 4 above to prompt you if an application tries to use the private key of this certificate.

Permission required to use the private key

DeliciousBookmark this on Delicious Share