Back to home

Managing Secrets with Azure KeyVault in Sitecore AKS Cluster and Configuring the Release Pipeline

Overview

When it comes to managing the secrets, it is not good to store them as part of the code repository. Managing the secrets in PaaS Azure Web Apps would be straightforward. You can simply store the secrets in the Azure KeyVault and it can be referenced. But when we deploy to AKS containers with yaml specification files, it is bit different and we are going to see how it can be done.

As you are seeing below, The Sitecore Kubernetes deployment uses secrets to store sensitive information. If the AKS cluster provisioning is done from the code repository following the InfraStructure as Code principle, then all these secrets will be residing in our source control repository as plain text.

You can download the Sitecore 10.3 XM’s container deployment package from this link to know more about it.

So how we are going to use Azure Key Vault to move these sensitive information and use it from there ? Let us see this in detail.

Note:- This blog will not explain about Sitecore Kubernetes CI/CD configuration completely. But its going to be only about the specific tasks that are responsible for the secret managements with Azure KV.

Adding the secrets to the k8s specification file

We have to add one .txt file that holds a equivalent token like this for each of the secrets we would like to move to Azure KV. For example, let us take the Sitecore License secret as an example and see how it can be used from Azure KV. The sitecore-license.txt file holds a token $(sitecore-license).

This sitecore-license.txt file should be included in the kustomization.yaml file like this. I have included only this file below in the yaml specification to be more clear. But it should contain other default secrets as well. This kustomization.yaml is an index file that holds all the secrets needed.

generatorOptions:
  disableNameSuffixHash: true
secretGenerator:
- name: sitecore-license
  files:
  - sitecore-license.txt

It is also possible to add multiple secrets under one key group like this.

generatorOptions:
  disableNameSuffixHash: true
secretGenerator:
- name: {name of the group}
  files:
  - {secret-file-1.txt}
  - ....
  - {secret-file-n.txt}

So during the deployment, these secretes in the customization file will be applied and created in the kubernetes cluster when the following command is run.

kubectl apply -k ./secrets/

Configuring the secret in Azure KeyVault

You can add this sitecore-license secret in the azure keyvault like this with its actual value.

In case if this is the first time, you are going to move all these secrets into the KeyVault, then you can do this with the help some PSE scripts.

You don’t have to reinvent the wheel for this. You can refer this nice script that does this job from Rob Habraken. This script will use the kustomization.yaml as the index file to loop all the secret files and generate the corresponding key vault entries.

Now have both our k8s specification files updated with the desired key and the corresponding secret also created in the AKV. So let us see, what change we need to do in the release pipeline.

Replacing the tokens during the AKS release

This requires the below two steps,

  1. To download all the secrets from the AKV. So that it will be available for the tasks that follow this
  2. And then to replace the tokens with the actual secret value

I am using the Azure DevOps UI to configure the above tasks and use the end yaml configuration into my actual release pipeline yaml file.

Configuring the Azure Key Vault task

We need to use an Azure DevOps task for this. To configure this task, you can search it in the Task configuration UI from your release pipeline yaml file.

When you configure this, you can choose your azure subscriptions and correspoding KeyVault. The final task specification will be looking like this,

        - task: AzureKeyVault@2
          displayName: "Download from Keyvault"
          inputs:
            azureSubscription: '$(STG_AZURE_SUBSCRIPTION)'
            KeyVaultName: '$(STG_AZURE_KEYVAULT_QA)'
            SecretsFilter: '*'
            RunAsPreJob: false

Here the name of the azure subscription and the key vault names are taken from the pipeline variables in my case.

Configuring the Replace Tokens task

In the same we have done before, search for the ‘replace token’ in the task configuration UI panel to configure the Replace token task as well. This task replaces the token in the text files with the variable values from Azure KV.

The final yaml specification of this specific replace token task will be like this.

        - task: qetza.replacetokens.replacetokens-task.replacetokens@5
          inputs:
            rootDirectory: '$(System.ArtifactsDirectory)/k8s/qa'
            targetFiles: |
              **/*.txt
              **/*.crt
              **/*.key
              **/*.yaml
            encoding: 'auto'
            tokenPattern: 'azpipelines'
            writeBOM: true
            actionOnMissing: 'warn'
            keepToken: true
            actionOnNoFiles: 'continue'
            enableTransforms: false
            useLegacyPattern: false
            enableTelemetry: false

In the above task, please note that the target file is set to txt, crt, key and yaml. Because we are going to process these file types to replace the tokens with its actual value from Azure KV.

You can refer this link to know more above this Replace Tokens and its different options.

Now this can be used from any pod yaml specification files like how its explained in the below section.

Using the secret in a pod configuration

If you refer the Identity server’s id.yaml specification file as an example, the license key is referred like this. Here the secrets from the Kubernetes secret store will be mounted to the pods.

With these configuration, when the release pipeline is run, the secrets are pulled from Azure keyvault and the tokens are replaced by the actual value.

Result of the download token from azure key vault task.

Result of the replace token task in the release pipeline. You can notice that the token sitecore-license got replaced by the actual value from Azure KV.

Let us also check the ID pod in the kubernetes cluster to see whether the actual value got replaced from the KV.

References:

  1. https://github.com/qetza/vsts-replacetokens-task
  2. https://doc.sitecore.com/xp/en/developers/101/managed-cloud/add-a-kubernetes-secret.html
  3. https://github.com/Sitecore/container-deployment/releases/tag/sxp%2F10.3.0.008463.1135
  4. https://github.com/robhabraken/paas-to-aks
  5. https://www.sitecore.com/knowledge-center/getting-started/sitecore-docker-and-continuous-integration