Custom domain name and certificate for your Azure Service Fabric cluster

This is a follow-up to my previous post about getting SSL working on a local Azure Service Fabric cluster. This time I'm aiming for the real goal: running a custom API endpoint (micro-service) on a custom domain name behind https on a cluster running on Azure.

First a short summary of the things we need to do:

  • Register a CNAME record with a DNS provider that maps your desired custom domain name to the default domain name of your Service Fabric cluster.
  • Obtain a certificate in PFX format from a certificate authority.
  • Upload the PFX file to Azure Key Vault.
  • Modify the Azure Virtual Machine Scale Set that sits behind your Service Fabric cluster so that the certificate gets installed on all VMs in the scale set.
  • Modify the Service Fabric configuration to make sure that our custom API uses the certificate.

Register a DNS CNAME record

This step actually has nothing to do with Service Fabric but is required if you want to run your API micro-service on SSL (or you could try getting a certificate for mysfcluster.westeurope.cloudapp.azure.com but I don't think Microsoft will allow that ;)

So what you want is a CNAME record that maps your custom domain name, for this article I'll use mysfcluster.nl, to the domain of your cluster, e.g. mysfcluster.westeurope.cloudapp.azure.com.

Get a certificate

Again, this has nothing to do with Service Fabric. You need a server authentication certificate in PFX format that includes the private key and the entire certificate chain. And of course the password that protects the private key.

Upload the certificate to Azure Key Vault

Azure Key Vault can be used to securely store a number of different things: passwords, PFX files, storage account keys, etc. Things you store there can be referenced from Azure Resource Manager templates to be used in web sites, VMs, etc. Uploading a PFX file to Azure Key Vault isn't as easy as it should be, so lucky for us Chacko Daniel from Microsoft has written a nice PowerShell module that handles this for us.

So what I did was clone the GitHub repository and import the module (from a PowerShell prompt):

PS c:\projects> git clone https://github.com/ChackDan/Service-Fabric.git  
PS c:\projects> Import-Module Service-Fabric\Scripts\ServiceFabricRPHelpers\ServiceFabricRPHelpers.psm1  

We can now invoke the PowerShell command Invoke-AddCertToKeyVault, which you'll find below, including the expected output.

PS C:\projects> Invoke-AddCertToKeyVault `  
        -SubscriptionId "12345678-aabb-ccdd-eeff-987654321012" `
        -ResourceGroupName MySFResourceGroup `
        -Location westeurope `
        -VaultName "MyKeyVault" `
        -CertificateName "MyAPICert" `
        -Password "eivhqfBw=AGUsLuJ2Z<r" `
        -UseExistingCertificate `
        -ExistingPfxFilePath "C:\projects\mysfcluster_nl.pfx"

Switching context to SubscriptionId 12345678-aabb-ccdd-eeff-987654321012  
Ensuring ResourceGroup MySFResourceGroup in westeurope  
Using existing vault MyKeyVault in westeurope  
Reading pfx file from C:\projects\mysfcluster_nl.pfx  
Writing secret to MyAPICert in vault MyKeyVault

Name  : CertificateThumbprint  
Value : C83D60162D7BDC62A41516CD5007E4FDDD196201

Name  : SourceVault  
Value : /subscriptions/12345678-aabb-ccdd-eeff-987654321012/resourceGroups/MySFResourceGroup/providers/Microsoft.KeyVault/vaults/MyKeyVault

Name  : CertificateURL  
Value : https://mykeyvault.vault.azure.net:443/secrets/MyAPICert/e72e1834a1ae4be19f249121cc8fc722  

I'll walk you through the parameters for Invoke-AddCertToKeyVault in order of appearance:

SubscriptionIdThe id of the Azure subscription that contains your key vault. When the key vault does not yet exist, it will be created.
ResourceGroupNameName of the resource group for your key vault.
LocationKey vault location. If you run the PowerShell cmd Get-AzureRmLocation you'll get a list of location system names.
VaultNameThe name of your key vault. When the script can not find this key vault, it will be created.
CertificateNameThe name of the PFX resource that is created in the key vault.
PasswordThe password that you used to protect the private key in the PFX file.
UseExistingCertificateIndicates that we are using an existing certificate. Invoke-AddCertToKeyVault can also be used to generate a self-signed certificate and upload that to the key vault.
ExistingPfxFilePathThe absolute path to your PFX file.

Install certificate on virtual machines

An Azure Service Fabric cluster is powered by one or more Virtual Machine Scale Sets. A VM Scale Set is a collection of identical VMs that (in the case of Service Fabric) run the micro-services in your Service Fabric applications.

There is very little support for VM Scale Sets in the portal so we use Azure Resource Explorer for this. If you've opened Azure Resource Explorer, you have to browse to the correct resource, which is the VM Scale Set that powers your SF cluster. In my case, it is called Backend.

Resource Explorer left pane

Once there, you can add a reference to the certificate in the key vault. In the screenshot below, you see a reference to the key vault itself and multiple certificate references.

If I follow my own example:

  • the reference to the key vault should be /subscriptions/12345678-aabb-ccdd-eeff-987654321012/resourceGroups/MySFResourceGroup/providers/Microsoft.KeyVault/vaults/MyKeyVault
  • the reference to the certificate should be https://mykeyvault.vault.azure.net:443/secrets/MyAPICert/e72e1834a1ae4be19f249121cc8fc722

You can copy these values from the output of the Invoke-AddCertToKeyVault command. If you save (PUT) the updated VM Scale Set resource description, the certificate will be installed to all VMs in the scale set.

Configure Service Fabric to use the certificate

We actually already did this in the previous post so I'll summarize here:

  1. Extend your ServiceManifest.xml with an additional named (https) endpoint.
  2. Extend the ApplicationManifest.xml in two places:
    • Add an EndpointBindingPolicy to the ServiceManifestImport. This links the https endpoint to a certificate.
    • Add an EndpointCertificate to the certificates collection. This is a named reference to the thumbprint of the certificate you uploaded to Azure Key Vault earlier.
  3. Modify OwinCommunicationListener. This class is hard-coded to support only http. You can change this to make it support https as well.
  4. Add a ServiceInstaleListener that references the https endpoint.

For more information about service manifests, application manifest and how they are related, check this post.

Conclusion

There are again quite some steps involved, just as in the previous post on how to get this working locally. Each step by itself isn't complicated but the entire process takes some time and effort.

I hope this helps in setting up a protected endpoint in Service Fabric :)