Azure Kubernetes Service KeyVault access with Dapr

An alternative method for gaining access to KeyVault secrets from applications in Azure Kubernetes Service is through the use of Dapr. Dapr will run as a sidecar in your Kubernetes cluster. Although it is lightweight and provides much simpler access, it should be noted that Dapr effectively creates additional pods in your cluster and therefore may need some considerations in edge case scenarios where pod limits are being reached. It adds up to 7 different services and 4 different pods in its own namespace. It is something to always keep in mind for keeping an eye on resource usage/limits/quotas in the AKS cluster as you expand.

Note that it might be helpful to leverage knowledge on Workload Identity and Federated Identity from my previous post that will dovetail into what I write here. Ultimately, using Dapr with AKS will add more Infrastructre complexity but simplify application code complexity.

Install Dapr on AKS

Install Dapr onto your AKS Cluster with the following Azure CLI commands:

//login flow
az login

az extension add --name k8s-extension
az provider register --namespace Microsoft.KubernetesConfiguration

az feature registration create --namespace Microsoft.KubernetesConfiguration --name ExtensionTypes

//answer N if Dapr is not already installed on your cluster or y if it is
//this will take a little while
az k8s-extension create --cluster-type managedClusters --cluster-name [your_AKSCluster_Name] --resource-group [your_ResourceGroup] --name dapr --extension-type Microsoft.Dapr --auto-upgrade-minor-version true

Installing Dapr onto AKS

Set Managed Identity for AKS Cluster

Create a managed identity via the Azure CLI as follows:

az identity create --name [Your_ManagedIdentityName] --resource-group [Your_ResourceGroupName]

Create a new Managed Identity

Note down the 'id' and the 'ClientId' shown in the response json here.

Assign your ManagedIdentity to your existing AKS Cluster as an assigned Managed Identity:

//use the 'id' from the previous command as the Managed_Identity_ResourceID here
az aks update --resource-group [Your_ResourceGroup] --name [Your_AKSCluster_Name] --enable-managed-identity --assign-identity [ManagedIdentity_id_from_previous_step]

Assigning a Managed Identity to an AKS Cluster

Next you will need to make sure that you Federate your Managed Identity (see here on how we did this in a previous post)

Set Permissions for Managed Identity to KeyVault

Set the necessary permissions you need for your needs

//now use the 'clientid' from the previous step
az keyvault set-policy --name [Your_KeyVault_Name] --object-id [Your_ManagedIdentity_ClientId] --secret-permissions get set

Set permissions you need with an Access Policy for the Managed Identity on the KeyVault

Set a Secret Store Dapr Component

The AKS Cluster will need a secret store component applied to use for the KeyVault:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: azurekeyvaultdapr
  namespace: default
spec:
  type: secretstores.azure.keyvault
  version: v1
  metadata:
  - name: vaultName
    value: [your_keyvault_name]
  - name: azureClientId
    value: [your_ManageIdentity_ClientId]

Dapr secret store yaml

Deploy the above by using:

kubectl apply -f [yourdaprKeystore.yaml]

Dapr key store deployment

Deploy Deployment and Service YAML

We can use the following deployment and Service YAML, this time with specific annotations for the Dapr sidecar on our deployment YAML:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: demoappdeployment
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: demoapp
  template:
    metadata:
      labels:
        app: demoapp
        azure.workload.identity/use: "true"
      annotations:
        dapr.io/enabled: "true"           # Enables Dapr sidecar injection
        dapr.io/app-id: "demoapp"       # Unique ID for your application
        dapr.io/app-port: "80"          # Port your application listens on
    spec:
      serviceAccountName: podserviceaccount ## this is detailed in the next section
      containers:
      - name: demoapp
        image: <yourapp_docker_imagelocation>
        ports:
        - containerPort: 80
        env:
        - name: ASPNETCORE_HTTPS_PORTS
          value: "8081"
        - name: ASPNETCORE_HTTP_PORTS
          value: "80" 

---

apiVersion: v1
kind: Service
metadata:
  name: demoservicedapr
spec:
  selector:
    app: demoapp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: LoadBalancer


Deployment.yaml (including Service yaml)

Deploy the above by using:

kubectl apply -f [deployment.yaml]

Deployment and Service yaml deployment

Set Service Account YAML

You will need a Service account for the AKS cluster to use where the Managed Identity you select is Federated (this links back to my previous post that included how )

apiVersion: v1
kind: ServiceAccount
metadata:
  name: podserviceaccount
  namespace: default
  annotations:
    azure.workload.identity/client-id: "your_managedIdentity_ClientId"
  labels:
    azure.workload.identity/use: "true" 

serviceaccount.yaml example

Deploy the above by using:

kubectl apply -f [serviceaccount.yaml]

Access KeyVault Secret using Dapr in AKS

You can package and deploy an app with the following example code to a Docker Container Registry to access an existing secret from an Azure Key Vault using Dapr:

Add the Dapr nuget package to your project:

dotnet add package Dapr.Client --version 1.14.0

Add Dapr nuget package

Example:

//assuming .NET6
public class HomeController : Controller
 {

     public class ArbitraryData
     {
         public string SecretData { get; set; }
     }
     
     public async Task<IActionResult> Index()
     {

         var daprClient = new DaprClientBuilder().Build();
       
        //get existing secret here
         var secret = await daprClient.GetSecretAsync("azurekeyvaultdapr", "ContextLength");
         Console.WriteLine($"Secret value: {secret["ContextLength"]}");
         var result = new ArbitraryData()
         {
             SecretData = "The aks data is " +  secret["ContextLength"] + $" From Dapr - {DateTime.UtcNow}" 
         };
         return View(result);
     }
}

Quick C# code for reading values from Key Vault with Dapr

When you get to the LodBalancer External IP Address:

Retrieving a value from KeyVault from within AKS with Dapr

That's it. REMEMBER TO DELETE UNUSED RESOURCES IN AZURE!!!