Table of Contents
Creating a Helm Chart for Azure SecretProvider
Summary: This wiki page shows how to create a helm chart for the Azure Secretprovider.
Date: 16 Janauray 2026
This is the wiki page on how the helm chart azure-secretprovider was created. The helm chart is used to create a SecretProviderClass manifest for AKS with workload identity enabled. After creating the chart and some example values file, I'll also show how to create a helm repository in Azure and how to publish the chart there. Finally, I'll also show an overview of how a secretprovider actually works in AKS with workload identity enabled.
Create a Helm Chart
Creating a Helm chart is very straightforward. If you already have a working environment with helm installed, you can simply run the following command to create a new chart:
helm create azure-secretprovider
This command will generate a directory structure for your Helm chart with some default files and folders. After that, and when looking at the documentation, the next step would be to remove all of the files and add your own. Now, creating a helm chart is very easy because all you need to do is adding a manifest file in the `templates` folder. That's all. Whenever you then do a helm install, it will just install that manifest. Of course, you can also use values, variables and more, which is what we'll do.
I used the following steps to create the chart, using the WSL installation I described earlier:
helm version
# Output: version.BuildInfo{Version:"v3.16.1", GitCommit:"5a5449dc42be07001fd5771d56429132984ab3ab", GitTreeState:"clean", GoVersion:"go1.22.7"}
helm create azure-secretprovider
A new folder is created called `azure-secretprovider`. After checking the files, I performed the following steps:
- Removed the empty directory `charts`
- Removed the directory `templates/tests`
- Updated the Chart.yaml file with relevant information about the chart
- From the `templates` folder, removed all files except for `_helpers.tpl` and `NOTES.txt`
- Updated the `NOTES.txt` file with a link to this wiki page
- Created a new file `secretproviderclass.yaml` in the `templates` folder
- Created a template for the SecretProviderClass manifest, using values from `values.yaml`
- Removed the content of the default `values.yaml` file and updated it with relevant parameters for the SecretProviderClass
Validate the Helm Chart
First, we can validate the chart using helm lint:
$ helm lint ./azure-secretprovider ==> Linting ./azure-secretprovider 1 chart(s) linted, 0 chart(s) failed
Next, we can generate an empty template using helm template:
$ helm template azure-secretprovider ./azure-secretprovider --- # Source: azure-secretprovider/templates/secretproviderclass.yaml apiVersion: secrets-store.csi.x-k8s.io/v1 kind: SecretProviderClass metadata: name: azure-secretprovider spec: provider: azure parameters: keyvaultName: objects: | array: tenantId: usePodIdentity: "false" clientID:
So far, everything looks good. Now, let's create some values files.
Values Files
I have created various values files for different use cases.
Grafana
The following values file creates two secrets, one for the Grafana admin credentials and one for the Grafana Slack Webhook. The first secret has two keys, while the second secret has one key:
tenantId: 7e4an71d-a123-a123-a123-abcd12345678 clientID: acc78f4a-932a-415f-a77e-e7e1071a0161 keyvaultName: kv-euw-shift secrets: - Grafana-AdminPassword - Grafana-AdminUsername - Grafana-SlackWebHook secretObjects: - secretName: grafana-admin data: - key: admin-password objectName: Grafana-AdminPassword - key: admin-user objectName: Grafana-AdminUsername type: Opaque - secretName: grafana-slackwebhook data: - key: SLACKWEBHOOK objectName: Grafana-SlackWebHook type: Opaque
If we would use this values file, we would render the following manifest:
$ helm template azure-secretprovider ./azure-secretprovider --values ./values/azure-secretprovider-grafana.yaml --- # Source: azure-secretprovider/templates/secretproviderclass.yaml apiVersion: secrets-store.csi.x-k8s.io/v1 kind: SecretProviderClass metadata: name: azure-secretprovider spec: provider: azure parameters: keyvaultName: kv-euw-shift objects: | array: - | objectName: Grafana-AdminPassword objectType: secret - | objectName: Grafana-AdminUsername objectType: secret - | objectName: Grafana-SlackWebHook objectType: secret tenantId: 7e4an71d-a123-a123-a123-abcd12345678 usePodIdentity: "false" clientID: acc78f4a-932a-415f-a77e-e7e1071a0161 secretObjects: - data: - key: admin-password objectName: Grafana-AdminPassword - key: admin-user objectName: Grafana-AdminUsername secretName: grafana-admin type: Opaque - data: - key: SLACKWEBHOOK objectName: Grafana-SlackWebHook secretName: grafana-slackwebhook type: Opaque
If needed, we could override one of the settings in the values file using --set: $ helm template azure-secretprovider ./azure-secretprovider --values ./values/azure-secretprovider-grafana.yaml --set keyvaultName=kv-euw-shift-dev
Certificate
The following values file creates a secret for a certificate:
secrets: - getshifting-tls-cert - getshifting-tls-key secretObjects: - secretName: getshifting-tls data: - key: tls.crt objectName: getshifting-tls-cert - key: tls.key objectName: getshifting-tls-key type: kubernetes.io/tls
Creating a Helm Repository in Azure
To create a helm repository in Azure, we can use Azure Container Registry (ACR). ACR supports hosting helm charts, so we can push our chart to ACR and then use it as a helm repository. To create the repositor, we can go to Azure Cloud Shell and run the following commands:
# Variables $project = "acrshift" $rg = "rg-$project" $loc = "westeurope" # Create resource group az group create ` --name $rg ` --location $loc # Create Azure Container Registry az acr create ` --name "$project" ` --resource-group $rg ` --sku Basic ` --location $loc ` --public-network-enabled true
Push the Helm Chart to ACR
Now that we have created an Azure Container Registry, we can package our helm chart and push it to the ACR. Let's first package the chart:
helm package ./azure-secretprovider
Note that in the output of the command, you will see the path to the generated .tgz file. This is the file that we will push to ACR.
Next, we can push the chart to ACR. To do so, let's login to the ACR helm repository, amd then push the chart:
az login # Make sure you're logged in to the correct subscription az account set --subscription "30b3c71d-a123-a123-a123-abcd12345678" # Login to ACR helm repository USER_NAME="00000000-0000-0000-0000-000000000000" ACR_NAME="acrshift" PASSWORD=$(az acr login --name "$ACR_NAME" --expose-token --output tsv --query accessToken --only-show-errors) echo "$PASSWORD" | helm registry login "$ACR_NAME.azurecr.io" --username $USER_NAME --password-stdin # Push the chart to ACR helm push azure-secretprovider-0.1.0.tgz oci://"$ACR_NAME".azurecr.io/helm
Using the Helm Chart from ACR
ER gaat van alles mis, aantekeningen:
/mnt/c/Repos/GetShifting/knowledge/drafts/helmchart (main)
note: helm repo add werkt niet omdat helm repo niet werkt met OCI registries
Once the chart is pushed to the ACRR, we can check the ACR for existing charts and view their manifests:
# List the helm charts in the ACR $ az acr repository list --name $ACR_NAME [ "helm/azure-secretprovider" ] # Show the details of the helm chart in the ACR $ az acr repository show --name $ACR_NAME --repository helm/azure-secretprovider { "changeableAttributes": { "deleteEnabled": true, "listEnabled": true, "readEnabled": true, "writeEnabled": true }, "createdTime": "2026-02-06T16:32:05.1518971Z", "imageName": "helm/azure-secretprovider", "lastUpdateTime": "2026-02-06T16:32:05.3101879Z", "manifestCount": 1, "registry": "acrshift.azurecr.io", "tagCount": 1 }
To use the helm chart from ACR, we can add the ACR helm repository to our local helm client, and then install the chart from there:
# Add ACR helm repository helm repo add "$ACR_NAME" oci://"$ACR_NAME".azurecr.io/helm # Update helm repositories helm repo update # Install the chart from ACR using a local values file $ helm template azure-secretprovider oci://$ACR_NAME.azurecr.io/helm/azure-secretprovider --values ./values/azure-secretprovider-grafana.yaml Pulled: acrshift.azurecr.io/helm/azure-secretprovider:0.1.0 Digest: sha256:e10671232d69e5da0d662fd2c7bacfb621caf04a100d545334bf96b045d5315c --- # Source: azure-secretprovider/templates/secretproviderclass.yaml apiVersion: secrets-store.csi.x-k8s.io/v1 kind: SecretProviderClass metadata: name: azure-secretprovider spec: provider: azure parameters: keyvaultName: kv-euw-shift objects: | array: - | objectName: Grafana-AdminPassword objectType: secret - | objectName: Grafana-AdminUsername objectType: secret - | objectName: Grafana-SlackWebHook objectType: secret tenantId: 7e4an71d-a123-a123-a123-abcd12345678 usePodIdentity: "false" clientID: acc78f4a-932a-415f-a77e-e7e1071a0161 secretObjects: - data: - key: admin-password objectName: Grafana-AdminPassword - key: admin-user objectName: Grafana-AdminUsername secretName: grafana-admin type: Opaque - data: - key: SLACKWEBHOOK objectName: Grafana-SlackWebHook secretName: grafana-slackwebhook type: Opaque
As you can see from the 'Pulled' output, the chart is now pulled from the Azure Container Registry, and then together with the values file successfully rendered.
How does the SecretProviderClass work in AKS with Workload Identity Enabled
Now that we have created a helm chart for creating an Azure Secret Provider targeted on AKS with workload identity enabled, I also want to briefly show how the secretprovider works. Because of the workload identity and the central role of a secret provider, I created a diagram to show how the secretprovider works in AKS with workload identity enabled:
As you may note, the overview is for a secretprovider for grafana. This allowed for something extra, because in this setup grafana is also configured to use workload identity to access Azure monitor.
Note that the helm chart for Grafana is listed as a mix of the helm chart and the rendered manifest. This way it shows exactly what values are important for this setup.
Useful Links
This wiki has been made possible by:

