Xero Partner SSL configuration in Azure

Recently we became a Xero partner, which meant that we had to go through the process of converting our public API application to a partner one, which involves some custom SSL certificates which can easily trip you up in an Azure environment. I'll be going through the steps we took to make this work as the exact process can be a little tricky.

  1. Generate and download Xero signing certificates
  2. Generate PFX
  3. Get Entrust root certificate
  4. Update your API integration
  5. Install certificates to Azure
  6. Configure Azure roles

Generate and download Xero signing certificates

Certificate list

I'm going to assume that you have already got your self-signed certificate and have downloaded the certificate provided by Xero as this is all standard process when becoming a Xero partner. If you do not already have these go and get them, I'll wait.

Right, you should have 2 certificates now, 1 from the Xero download (renamed to Timestamp Xero Entrust Certificate.p12) and the self-signed certificate (Timestamp Xero Signing.cer and Timestamp Xero Signing.pfx in our case).

Generate PFX

The next step is to create a PFX file that can be imported and used within your worker / web roles. To do this import the Xero-downloaded .p12 certificate (put it in your personal store to allow local testing) using certificate manager (certmgr.msc) and export with a private key. Make sure you pick a strong password, and make sure not to lose it as you will need it again later!

Certificate store

Get Entrust root certificate

Entrust root certificate

An additional certificate is required when running from Azure, the Entrust Root Certificate, which can be downloaded from https://enrollcompriv.managed.entrust.com/cda-cgi/clientcgi.exe?action=start. Download the .cer file by clicking the Install link under CA Certificates. In our case we have renamed it to Timestamp Xero Entrust Root.cer instead of clientcgi.cer.

Update your API integration

Once you have all the required certificates you are ready to change your code to access the Xero API as a partner. When we started our integration the new .NET SDK (Xero-Net) was not available, so the code below is for the older SDK (XeroAPI.Net), although the same patterns should apply:

using System;
using System.Configuration;
using System.Security.Cryptography.X509Certificates;
using DevDefined.OAuth.Consumer;
using DevDefined.OAuth.Logging;
using XeroApi.OAuth;
 
public class XeroSessionFactory 
{
    public OAuthSession Create()
    {
        var userAgent = ConfigurationManager.AppSettings["xero:UserAgent"];
        var clientKey = ConfigurationManager.AppSettings["xero:ConsumerKey"];
    
        // These two values come from our configuration file. They are the distinguished names of our certificates
        // from the previous steps (e.g. CN=Timestamp, O=Xero, C=NZ for the SslEntrustCert config option)
        var signingCert = GetCertificateFromStore(ConfigurationManager.AppSettings["xero:SigningCert"]);
        var sslCert = GetCertificateFromStore(ConfigurationManager.AppSettings["xero:SslEntrustCert"]);
    
        // We use a custom database token repository, here you should use the same token repository as
        // you have used to develop your integration up until now
        var tokenRepository = new InMemoryTokenRepository();
    
        return new XeroApiPartnerSession(
            userAgent, 
            clientKey, 
            signingCert, 
            sslCert, 
            tokenRepository)
            {
                MessageLogger = new DebugMessageLogger()
            };
    }
    
    private static X509Certificate2 GetCertificateFromStore(string certName)
    {
    	// We use the CurrentUser store location here, which is why we imported in to the personal
    	// store earlir for local testing.
        var store = new X509Store(StoreLocation.CurrentUser);
    
        try
        {
            store.Open(OpenFlags.ReadOnly);
    
            var certCollection = store.Certificates;
            var currentCerts = certCollection.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
            var signingCert = currentCerts.Find(X509FindType.FindBySubjectDistinguishedName, certName, false);
    
            if (signingCert.Count == 0)
            {
                throw new InvalidOperationException(
                    string.Format("Could not find Xero SSL certificate. cert_name={0}", certName));
            }
    
            return signingCert[0];
        }
        finally
        {
            store.Close();
        }
    }
}

In the above code we are creating an OAuthSession of type XeroApiPartnerSession. During development you would have had this be created as a XeroApiPublicSession with similar parameters. The difference here is you will be using the certificates and not a client key & secret.

Install certificates to Azure

Once the above has been completed and you can successfully access the Xero API using the certificates in partner mode it is time to move on to configuring Azure, which involves 2 steps. The first is to upload the 3 certificate from earlier (2 .pfx and 1 .cer) to your web or worker role within the Azure portal, the second to configure the cloud service to install these certificates as required.

Upload the certificates to your Azure Cloud Service by going to the certificates tab, clicking upload at the bottom and selecting the 3 certificates, entering your passwords for the PFX files from earlier.

Configure Azure roles

Once that is done you need to configure these certificates in your cloud service. You can do this by modifying the .cscfg and .csdef file for your cloud service:

<WorkerRole name="Timestamp.TaskProcessor">
    <Certificates>
      <Certificate name="XeroAddOnSslSigning"
                   storeLocation="CurrentUser"
                   storeName="My" />
 
      <Certificate name="XeroAddOnEntrust"
                   storeLocation="CurrentUser"
                   storeName="My" />
 
      <Certificate name="XeroAddOnEntrustRoot"
                   storeLocation="CurrentUser"
                   storeName="My" />
    </Certificates>
</WorkerRole>
<ServiceConfiguration>
  <Role name="Timestamp.TaskProcessor">
    <Instances count="1" />
 
    <Certificates>
      <Certificate name="XeroAddOnSslSigning"
          thumbprint="6a...73"
          thumbprintAlgorithm="sha1" />
 
      <Certificate name="XeroAddOnEntrust"
          thumbprint="f6...ed"
          thumbprintAlgorithm="sha1" />
 
      <Certificate name="XeroAddOnEntrustRoot"
          thumbprint="B5...0F"
          thumbprintAlgorithm="sha1" />
    </Certificates>
  </Role>
</ServiceConfiguration>

Now that you have got your cloud service configured it is time to deploy and test your changes. Hopefully this is as easy as setting off a new build in your CI build system. If not, why not look at that as your next step. Repeatable builds is a must for any project, but even more so with the complexities of a cloud development environment.

Resources

Update 19th June 2015

This post originally contained incorrect information about where the Entrust Root Certificate came from, stating it was in the download from Xero. This has been corrected with the correct link and instructions about where to get this certificate from.

Adam Barclay