9
9
Table of Contents

Introduction

The Azure Key Vault Provider for Secrets Store CSI Driver facilitates the seamless integration of an Azure Key Vault as a secure secret store with an Azure Kubernetes Service (AKS) cluster through the utilization of Container Storage Interface (CSI) volumes. This guide demonstrates how to implement and use the Azure Key Vault Provider for Secrets Store CSI Driver in AKS clusters. It covers integration steps, benefits, and best practices for secure secret management, including setup, configuration, and practical use cases to enhance Kubernetes application security. 

How it works

The diagram below illustrates how Secrets Store CSI volume works:

secrets store csi driver
Just like Kubernetes secrets, upon the initialization and restart of a pod, the Secrets Store CSI driver interacts with the external Secrets Store through gRPC to fetch the secret content specified in the SecretProviderClass custom resource. This content is then mounted within the pod as a `tmpfs` volume, and the secret data is written into that volume.

When a pod is deleted, the corresponding volume is cleaned up and deleted. 

Features

While Kubernetes secrets provide a basic mechanism for storing such data, they may not offer the robust security measures required for certain scenarios. Secrets Store CSI Driver’s notable features make it a preferred choice for organizations seeking a robust and flexible secret management solution:

1. Mounts secrets, keys, and certificates to a pod using a CSI volume. Secrets are directly mounted in the pod’s volume so secrets cannot be accessed directly outside the pod. 
2. Kubernetes secrets are not secure. Secrets Store CSI Driver uses external secret stores to store the secrets which are more secure.
3. Secrets Store CSI Driver does not store secrets in etcd and supports CSI inline volumes.
4. Supports mounting multiple secrets store objects as a single volume.
5. Supports pod portability with the SecretProviderClass CRD.
6. Supports Windows containers.
7. Syncs with Kubernetes secrets.
8. Supports autorotation of mounted contents and synced Kubernetes secrets.
9. Create an AKS cluster with Azure Key Vault Provider for Secrets Store CSI Driver support

Solution approach

Implementing the Azure Key Vault Provider for Secrets Store CSI Driver involves a strategic approach to ensure secure and effective deployment within your AKS cluster. Follow these steps for a successful setup:

  • Install the driver and providers in either the kube-system namespace or a dedicated namespace. The driver is deployed as a DaemonSet and requires permissions to mount kubelet hostPath volumes and access pod service account tokens. It should be handled as a privileged component, and regular cluster users should not have the authority to deploy or modify it.
  • The above point can be ignored if you are installing the CSI driver by enabling azure-keyvault-secrets-provider as add-ons (which we’ll be using in this blog); the AKS handles this on its own.

Prerequisites:

  • Check that your version of the Azure CLI is 2.30.0 or later. If it's an earlier version, install the latest version.
  • If you're restricting Ingress to the cluster, make sure ports 9808 and 8095 are open.

Steps:

1. Create an Azure resource group using the [az group create] command.

2. Create an AKS cluster with Azure Key Vault Provider for Secrets Store CSI Driver capability using the az aks create command and enable the azure-keyvault-secrets-provider add-on.

If you are using Azure Portal then the option to enable secret store CSI driver can be found in the `Advanced` options.

Upgrade an existing AKS cluster with Azure Key Vault Provider for Secrets Store CSI Driver support:

Upgrade an existing AKS cluster with Azure Key Vault Provider for Secrets Store CSI Driver capability using the az aks enable-addons command and enable the azure-keyvault-secrets-provider add-on. The add-on creates a user-assigned managed identity you can use to authenticate to your Azure key vault.


If you are using Azure Portal, the same addon can be enabled in Setting -> Cluster configurations.

3. Verify the Azure Key Vault Provider for Secrets Store CSI Driver installation:
Verify the installation is finished using the kubectl get pods command, which lists all pods with the secrets-store-csi-driver and secrets-store-provider-azure labels in the kube-system namespace.


4. Create or use an existing Azure key vault:
Create an Azure key vault using the az keyvault create command. The name of the key vault must be globally unique.

Your Azure key vault can store keys, secrets, and certificates.
In this example, the az keyvault secret set command is used to set a plain-text secret called secretName.

You can also create the Key Vault and Key vault secret using Azure portal.

Note: Azure role-based access control (Azure RBAC) should be configured for the key vault.

RBAC can be found in Access Configuration settings while creating the key vault.
5. Provide an identity to access the Azure Key Vault Provider for Secrets Store CSI Driver:

Access with a user-assigned managed identity-

Find the Client ID of the managed identity created by azure-keyvault-secrets-provider addon.
Use the following command to find the same-

The same can be found through Azure portal in managed identities. The name of the managed identity has a syntax: azurekeyvaultsecretsprovider-<clusterName>

Create a role assignment that grants the identity permission to access the key vault secrets, access keys, and certificates using the az role assignment create command.

6. Create a SecretProviderClass:
You can use the following YAML to create a SecretProviderClass-
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: azure-kv-spc
spec:
provider: azure
secretObjects:
  - data:
      - key: username
        objectName: secretName
      secretName: mysecret
      type: Opaque
parameters:
  usePodIdentity: "false"
  useVMManagedIdentity: "true"
  userAssignedIdentityID: <Managed_Identity's_Client_ID>
  keyvaultName: <Azure_Key_vault_name>
  objects:
    - |
      array:
        - |
          objectName: secretName
          objectType: secret
          objectVersion: ""
  tenantId: <tenant_ID>             


Note: 
a) No need to create k8s secret object separately. It will be created automatically when you create a pod with CSI driver volume.
b) The secretObjects block in the above YAML is optional and is only needed if you need to synchronize mounted content with a Kubernetes secret. You will still get the key vault object mounted to the pod if you do not use this block.

7. Set an environment variable to reference Kubernetes secrets:
Use the following YAML to reference your newly created Kubernetes secret by setting an environment variable in your pod:

kind: Pod
apiVersion: v1
metadata:
name: nginx-csi
spec:
containers:
  - name: nginx
    image: nginx
    volumeMounts:
      - name: secrets-store
        mountPath: "/mnt/secrets-store"
        readOnly: true
    env:
      - name: SECRET_USERNAME
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: username
volumes:
  - name: secrets-store
    csi:
      driver: secrets-store.csi.k8s.io
      readOnly: true
      volumeAttributes:
        secretProviderClass: "azure-kv-spc"


8. Validate the secrets:
a) Show secrets held in the secrets store using the following command.

b) Display a secret in the store using the following command. This example command shows the test secret secretName.

9. Enable and disable autorotation:
When the Azure Key Vault Provider for the Secrets Store CSI Driver is enabled, it periodically updates the mounted secrets within your pods and the corresponding Kubernetes secrets defined in the secretObjects field of your SecretProviderClass. This update process is initiated based on the rotation poll interval that you have configured. By default, the rotation poll interval is set to two minutes.
When a secret updates in an external secrets store after initial pod deployment, the Kubernetes Secret and the pod mount periodically updates.

a) Mount the Kubernetes Secret as a volume: Use the autorotation and Sync K8s secrets features of Secrets Store CSI Driver. The application needs to watch for changes from the mounted Kubernetes Secret volume. When the CSI Driver updates the Kubernetes Secret, the corresponding volume contents automatically update as well.
b)Application reads the data from the container’s filesystem: Use the rotation feature of Secrets Store CSI Driver. The application needs to watch for the file change from the volume mounted by the CSI driver.
c)Use the Kubernetes Secret for an environment variable: Restart the pod to get the latest secret as an environment variable. Use a tool such as Reloader to watch for changes on the synced Kubernetes Secret and perform rolling upgrades on pods.

Enable auto-rotation on a new AKS cluster:


Enable auto-rotation on an existing AKS cluster:


Specify a custom rotation interval:

Disable auto-rotation:
To disable autorotation, you first need to disable the add-on azure-keyvault-secrets-provider. Then, you can re-enable the add-on without the enable-secret-rotation parameter.

You can see the automatic change in value of the secretName after the autorotation interval.

But the same change won’t be reflected in the environment variable that is using this ‘secretName’ value. To reflect the change in this case you need to restart the pod.

Additional Examples

The following example illustrates the usage of multiple secrets from Azure Key Vault in a single SecretProviderClass YAML file:

secretProviderClass.yaml-
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: azure-kv-spc
spec:
provider: azure
secretObjects:
  - secretName: bucketsecret
    type: Opaque
    data:
      - key: DB-USER
        objectName: DB-USER
      - key: DB-PASSWORD
        objectName: DB-PASSWORD
      - key: DATABASE-HOST
        objectName: DATABASE-HOST
      - key: DATABASE-PORT
        objectName: DATABASE-PORT
      - key: DATABASE-NAME
        objectName: DATABASE-NAME      
parameters:
  usePodIdentity: "false"
  useVMManagedIdentity: "true"
  userAssignedIdentityID: <Managed_Identity's_Client_ID>
  keyvaultName: <key_vault_name>
  objects: |
    array:
      - |
        objectName: DB-USER
        objectType: secret
        objectVersion: ""
      - |
        objectName: DB-PASSWORD
        objectType: secret
        objectVersion: ""
      - |
        objectName: DATABASE-HOST
        objectType: secret
        objectVersion: ""
      - |
        objectName: DATABASE-PORT
        objectType: secret
        objectVersion: ""
      - |
        objectName: DATABASE-NAME
        objectType: secret
        objectVersion: ""
  tenantId: <tenant_id>

pod.yaml-

kind: Pod
apiVersion: v1
metadata:
name: nginx-csi
spec:
containers:
 - name: nginx
   image: nginx
   volumeMounts:
     - name: secrets-store
       mountPath: "/mnt/secrets-store"
       readOnly: true
   env:
     - name: DB_USER
       valueFrom:
         secretKeyRef:
           name: bucketsecret
           key: DB-USER
     - name: DB-PASSWORD
       valueFrom:
         secretKeyRef:
           name: bucketsecret
           key: DB-PASSWORD
     - name: DATABASE-HOST
       valueFrom:
         secretKeyRef:
           name: bucketsecret
           key: DATABASE-HOST
     - name: DATABASE-PORT
       valueFrom:
         secretKeyRef:
           name: bucketsecret
           key: DATABASE-PORT
     - name: DATABASE-NAME
       valueFrom:
         secretKeyRef:
           name: bucketsecret
           key: DATABASE-NAME
volumes:
 - name: secrets-store
   csi:
     driver: secrets-store.csi.k8s.io
     readOnly: true
     volumeAttributes:
       secretProviderClass: "azure-kv-spc"

Limitations

a) Enable Secret autorotation feature has been released in v0.0.15+ and is not available in  release v0.0.14 and earlier of Secrets Store CSI Driver.
b) Secrets not rotated when using subPath volume mount.

 volumeMounts:
  - mountPath: /app/spapi/settings.ini
    name: app-config
    subPath: settings.ini
...
volumes:
- csi:
    driver: secrets-store.csi.k8s.io
    readOnly: true
    volumeAttributes:
      secretProviderClass: app-config
  name: app-config

For more details refer to https://secrets-store-csi-driver.sigs.k8s.io/known-limitations.html

Conclusion

This guide provided a comprehensive walkthrough for implementing the Azure Key Vault Provider for Secrets Store CSI Driver in AKS clusters. It covered integration, benefits, and best practices for secure secret management, empowering users to enhance their Kubernetes application security and efficiently leverage Azure Key Vault. 

12
Let's discuss your cloud challenges and see how CloudKeeper can solve them all!
Meet the Author
  • Jatin Rautela
    DevOps Engineer

    Jatin is a DevOps Engineer with expertise and multiple certifications in Azure and AWS.

0 Comment
Leave a Comment

Speak with our advisors to learn how you can take control of your Cloud Cost