Jebarson's dev blog

Coffee, Code

Deploy & Access Certificates to Service Fabric Node from Azure Key Vault

If you are writing a secure code, there will be more than one instance where you need certificates to achieve encryption and decryption. Always depend on Azure Key Vault to read certificates and keys. However, there are many instances where you need the certificates to be installed in the node itself. This article is to address those specific scenario.

Before we go ahead and discuss the solution, I would want to highlights the dos and don’ts.

Best Practices

Dos:

  • Always store the certificates in Azure Key Vault.
  • Don’t let any users have ability to download certificates. Only your deployment service / pipeline should have access to it.
  • When possible, read the certificates from Azure Key Vault.
  • Install your certificate to nodes only when it is absolutely required.

Don’ts:

  • Never download certificates to your machine or check-in certificates to the repo.
  • Never hard-code certificate keys into your code.

Deployment

The first and foremost thing that you would want to do, is to tell the ARM template that your OS package will also need some certs to be installed. The section that dictates this, could be found in “OsProfile”. Your ARM template to deploy service fabric will have some setting as below.

"osProfile": {
            "adminPassword": "[parameters('adminPassword')]",
            "adminUsername": "[parameters('adminUsername')]",
            "computernamePrefix": "[parameters('vmNodeType0Name')]",
            "secrets": [
              {
                "sourceVault": {
                  "id": "[parameters('sourceVaultValue')]"
                },
                "vaultCertificates": [
                  {
                    "certificateStore": "[parameters('certificateStoreValue')]",
                    "certificateUrl": "[parameters('certificateUrlValue1')]"
                  },
                  {
                    "certificateStore": "[parameters('certificateStoreValue')]",
                    "certificateUrl": "[parameters('certificateUrlValue2')]"
                  }
                ]
              }
            ]
          }

In the above setting, we are defining a section “secrets” which could store the settings of certificates, keys etc. “sourceVault” is the resource url to the key vault and we have defined that as a parameter so that we can pass the value to it while deployment. “vaultCertificates” is a collection where we can define multiple certificates that will have two parameters; “certificateStore” will define the store it will be installed and “certificateUrl” will refer to resource url of the appropriate certificate in the key vault.

    "sourceVaultValue": {
      "type": "string",
      "defaultValue": "GEN-KEYVAULT-RESOURCE-ID",
      "metadata": {
        "description": "Resource Id of the key vault, is should be in the format of /subscriptions/<Sub ID>/resourceGroups/<Resource group name>/providers/Microsoft.KeyVault/vaults/<vault name>"
      }
    },
    "certificateUrlValue1": {
      "type": "string",
      "defaultValue": "GEN-KEYVAULT-SSL-SECRET-URI",
      "metadata": {
        "description": "Refers to the location URL in your key vault where the certificate was uploaded, it is should be in the format of https://<name of the vault>.vault.azure.net:443/secrets/<exact location>"
      }
    },
    "certificateUrlValue2": {
      "type": "string",
      "defaultValue": "GEN-KEYVAULT-SSL-SECRET-URI",
      "metadata": {
        "description": "Refers to the location URL in your key vault where the sti certificate was uploaded, it is should be in the format of https://<name of the vault>.vault.azure.net:443/secrets/<exact location>"
      }
    },
 "certificateStoreValue": {
      "type": "string",
      "allowedValues": [
        "My"
      ],
      "defaultValue": "My",
      "metadata": {
        "description": "The store name where the cert will be deployed in the virtual machine"
      }
    },

We have defined the appropriate parameters for the certificates as above. All that you have to do now is to pass these values appropriately while deploying the ARM template. If your intention is just to install the certificate, you can skip the rest of the article.


Access Permissions

If you would want to consume the certificate in your web API or application, you will need to define some policies to the manifest, so that the application has the rights to read the certificate while running.

Below is how your “ApplicationManifest.xml” will look like. You can find this file under “ApplicationPackageRoot” of your service fabric project.

<ApplicationManifest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ApplicationTypeName="MySvcFabricType" ApplicationTypeVersion="1.0.0" xmlns="http://schemas.microsoft.com/2011/01/fabric">
  <Parameters>
    <Parameter Name="MyWebApi_ASPNETCORE_ENVIRONMENT" DefaultValue="" />
    <Parameter Name="Certificate1_THUMBPRINT" DefaultValue="" />
    <Parameter Name="Certificate2_THUMBPRINT" DefaultValue="" />
    <Parameter Name="MyWebApi_InstanceCount" DefaultValue="1" />
  </Parameters>
  <!-- Import the ServiceManifest from the ServicePackage. The ServiceManifestName and ServiceManifestVersion 
       should match the Name and Version attributes of the ServiceManifest element defined in the 
       ServiceManifest.xml file. -->
  <ServiceManifestImport>
    <ServiceManifestRef ServiceManifestName="MyWebApiPkg" ServiceManifestVersion="1.0.0" />
    <ConfigOverrides />
    <EnvironmentOverrides CodePackageRef="code">
      <EnvironmentVariable Name="ASPNETCORE_ENVIRONMENT" Value="[MyWebApi_ASPNETCORE_ENVIRONMENT]" />
    </EnvironmentOverrides>
  </ServiceManifestImport>
  <DefaultServices>
    <!-- The section below creates instances of service types, when an instance of this 
         application type is created. You can also create one or more instances of service type using the 
         ServiceFabric PowerShell module.
         
         The attribute ServiceTypeName below must match the name defined in the imported ServiceManifest.xml file. -->
    <Service Name="MyWebApi" ServicePackageActivationMode="ExclusiveProcess">
      <StatelessService ServiceTypeName="MyWebApiType" InstanceCount="[MyWebApi_InstanceCount]">
        <SingletonPartition />
      </StatelessService>
    </Service>
  </DefaultServices>
  <Principals>
    <Users>
      <User Name="NETWORK SERVICE" AccountType="NetworkService" />
    </Users>
  </Principals>
  <Policies>
    <SecurityAccessPolicies>
      <SecurityAccessPolicy ResourceRef="Cert1" PrincipalRef="NETWORK SERVICE" ResourceType="Certificate" />
      <SecurityAccessPolicy ResourceRef="Cert2" PrincipalRef="NETWORK SERVICE" ResourceType="Certificate" />
    </SecurityAccessPolicies>
  </Policies>
  <Certificates>
    <SecretsCertificate X509FindValue="[Certificate1_THUMBPRINT]" Name="Cert1" />
    <SecretsCertificate X509FindValue="[Certificate2_THUMBPRINT]" Name="Cert2" />
  </Certificates>
</ApplicationManifest>

In the “Parameters” section, we defined two variables “Certificate1_Thumbprint” and “Certificate2_Thumbprint” which will allow you to define the thumbprints of the certificates in the publish profile.

The “Certificates” will define these certificates and assign them a name namely; “Cert1” and “Cert2”.

The “Policies” section will then define the user principals that will have access to these certificates.

Your appropriate publish profile (e.g. cloud.xml) will contain the thumbprint of the certificates that will be visible to your service.

Deploy & Access Certificates to Service Fabric Node from Azure Key Vault

2 thoughts on “Deploy & Access Certificates to Service Fabric Node from Azure Key Vault

  1. Nice articles on certificate usage in service fabric. However if we get away with thumbprint and start using subject name it will add one additional advantage. Full auto cert can be enabled end to end without user intervention. Because thumbprint changes with cert renewal but subject name remains same.

    Now key vault support issuing of certificates via one cert and it also supports auto renewal. Enabling auto rotation for certificate is super easy.

    1. It’s just a sample using the thumbprint. You can use any way you want. Yes, auto cert rotation is available but you will not get way with not needing to configure your manifest to include it.

      And yes, auto rotation is helpful in 99% of the cases. But there are few mission critical pieces of software where we want programmers to manually update the cert and test before pushing the changes.

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to top