Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
The Secrets Store Container Storage Interface (CSI) Driver on Azure Kubernetes Service (AKS) provides various methods of identity-based access to your Azure Key Vault. This article outlines these methods and best practices for when to use Azure role-based access control (Azure RBAC) or OpenID Connect (OIDC) security models to access your key vault and AKS cluster.
You can use one of the following access methods:
- Service Connector with managed identity
- Workload ID
- User-assigned managed identity
Learn how to connect to Azure Key Vault with the Secrets Store CSI Driver in an Azure Kubernetes Service (AKS) cluster using Service Connector. In this article, you complete the following tasks:
- Register the required Azure resource providers.
- Create a connection between the AKS cluster and the Azure Key Vault with Service Connector.
- Create a
SecretProviderClassCRD and aPodthat consumes the CSI provider to test the connection. - Verify that the pod can access the key vault secret.
Prerequisites
- An Azure account with an active subscription. Create an account for free.
- The Azure CLI. Sign in using the
az logincommand. - Docker and kubectl. To install kubectl locally, use the
az aks install-clicommand. - A basic understanding of containers and AKS. Get started by preparing an application for AKS.
- Before you begin, make sure you finish the steps in Use the Azure Key Vault provider for Secrets Store CSI Driver in an Azure Kubernetes Service (AKS) cluster to enable the Azure Key Vault Secrets Store CSI Driver in your AKS cluster.
Initial set-up
If you're using Service Connector for the first time, start by running the command az provider register to register the Service Connector and Kubernetes Configuration resource providers.
az provider register -n Microsoft.ServiceLinkeraz provider register -n Microsoft.KubernetesConfigurationTip
You can check if these resource providers have already been registered by running the commands
az provider show -n "Microsoft.ServiceLinker" --query registrationStateandaz provider show -n "Microsoft.KubernetesConfiguration" --query registrationState.Optionally, use the Azure CLI command to get a list of supported target services for AKS cluster.
az aks connection list-support-types --output table
Create a service connection in AKS with Service Connector
You can create a service connection to Azure Key Vault using the Azure portal or Azure CLI.
In the Azure portal, navigate to your AKS cluster resource.
From the service menu, under Settings, select Service Connector > Create.
On the Create connection page, configure the following settings in the Basics tab:
- Kubernetes namespace: Select default.
- Service type: Select Key Vault and select the checkbox to enable the Azure Key Vault CSI Provider.
- Connection name: Enter a name for the connection.
- Subscription: Select the subscription that contains the key vault.
- Key vault: Select the key vault you created.
- Client type: Select None.
Select Review + create, and then select Create to create the connection.
Test the connection
Clone the sample repo and deploy manifest files
Clone the sample repository using the
git clonecommand.git clone https://github.com/Azure-Samples/serviceconnector-aks-samples.gitChange directories to the Azure Key Vault CSI provider sample.
cd serviceconnector-aks-samples/azure-keyvault-csi-providerIn the
secret_provider_class.yamlfile, replace the following placeholders with your Azure Key Vault information:- Replace
<AZURE_KEYVAULT_NAME>with the name of the key vault you created and connected. - Replace
<AZURE_KEYVAULT_TENANTID>with the tenant ID of the key vault. - Replace
<AZURE_KEYVAULT_CLIENTID>with identity client ID of theazureKeyvaultSecretsProvideradd-on. - Replace
<KEYVAULT_SECRET_NAME>with the key vault secret you created. For example,ExampleSecret.
- Replace
Deploy the
SecretProviderClassCRD using thekubectl applycommand.kubectl apply -f secret_provider_class.yamlDeploy the
Podmanifest file using thekubectl applycommand.The command creates a pod named
sc-demo-keyvault-csiin the default namespace of your AKS cluster.kubectl apply -f pod.yaml
Verify the connection
Verify the pod was created successfully using the
kubectl getcommand.kubectl get pod/sc-demo-keyvault-csiAfter the pod starts, the mounted content at the volume path specified in your deployment YAML is available.
Show the secrets held in the secrets store using the
kubectl execcommand.kubectl exec sc-demo-keyvault-csi -- ls /mnt/secrets-store/Display a secret using the
kubectl execcommand.This example command shows a test secret named
ExampleSecret.kubectl exec sc-demo-keyvault-csi -- cat /mnt/secrets-store/ExampleSecret
Prerequisites for CSI Driver with workload identity
- Before you begin, make sure you finish the steps in Use the Azure Key Vault provider for Secrets Store CSI Driver in an Azure Kubernetes Service (AKS) cluster to enable the Azure Key Vault Secrets Store CSI Driver in your AKS cluster.
- Microsoft Entra Workload ID supports both Windows and Linux clusters.
Access with a Microsoft Entra Workload ID
A Microsoft Entra Workload ID is an identity that an application or service uses to authenticate itself against other Azure services, such as workloads in software. The Secrets Store CSI Driver integrates with native Kubernetes capabilities to federate with external identity providers.
In this security model, the AKS cluster acts as the token issuer. When the Secrets Store CSI Driver mounts the volume, it requests a Kubernetes service account token, and the Azure Key Vault provider exchanges that token for a Microsoft Entra token. The application reads the mounted files and doesn't need the Azure Identity client library or the Microsoft Authentication Library (MSAL) for this volume-mount flow. If the application independently requests Microsoft Entra tokens to call protected APIs, use Azure Identity or MSAL in the application.
Note
- This authentication method replaces Microsoft Entra pod-managed identity (preview). The open source Microsoft Entra pod-managed identity (preview) in Azure Kubernetes Service was deprecated as of October 24, 2022.
- Microsoft Entra Workload ID supports both Windows and Linux clusters.
Configure workload identity
Set your subscription using the
az account setcommand.export SUBSCRIPTION_ID=<subscription id> export RESOURCE_GROUP=<resource group name> export UAMI=<name for user assigned identity> export KEYVAULT_NAME=<existing keyvault name> export CLUSTER_NAME=<aks cluster name> az account set --subscription $SUBSCRIPTION_IDCreate a managed identity using the
az identity createcommand.Note
This step assumes you have an existing AKS cluster with workload identity enabled. If workload identity isn't enabled, see Enable workload identity on an existing AKS cluster to enable it.
az identity create --name $UAMI --resource-group $RESOURCE_GROUP export USER_ASSIGNED_CLIENT_ID="$(az identity show --resource-group $RESOURCE_GROUP --name $UAMI --query 'clientId' -o tsv)" export KEYVAULT_TENANT_ID="$(az keyvault show --name $KEYVAULT_NAME --query properties.tenantId -o tsv)"Create a role assignment that grants the workload identity permission to access the key vault secrets, access keys, and certificates using the
az role assignment createcommand.Important
- If you set your key vault with
--enable-rbac-authorizationand you're usingkeyorcerttype, assign theKey Vault Certificate Userrole to give permissions. - If your key vault is set with
--enable-rbac-authorizationand you're usingsecrettype, assign theKey Vault Secrets Userrole. - If your key vault isn't set with
--enable-rbac-authorization, you can use theaz keyvault set-policycommand with the--key-permissions get,--certificate-permissions get, or--secret-permissions getparameter to create a key vault policy to grant access for keys, certificates, or secrets. For example:
az keyvault set-policy --name $KEYVAULT_NAME --key-permissions get --secret-permissions get --object-id <identity-object-id>export KEYVAULT_SCOPE=$(az keyvault show --name $KEYVAULT_NAME --query id -o tsv) # Example commands for a key vault with Azure RBAC enabled using `key` and `secret` types az role assignment create --role "Key Vault Certificate User" --assignee $USER_ASSIGNED_CLIENT_ID --scope $KEYVAULT_SCOPE az role assignment create --role "Key Vault Secrets User" --assignee $USER_ASSIGNED_CLIENT_ID --scope $KEYVAULT_SCOPE- If you set your key vault with
Get the AKS cluster OIDC Issuer URL using the
az aks showcommand.Note
This step assumes you have an existing AKS cluster with the OIDC Issuer URL enabled. If the OIDC Issuer URL isn't enabled, see Update an AKS cluster with OIDC Issuer to enable it.
export AKS_OIDC_ISSUER="$(az aks show --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME --query "oidcIssuerProfile.issuerUrl" -o tsv)" echo $AKS_OIDC_ISSUERCreate a Kubernetes service account for the workload. Update the values for
SERVICE_ACCOUNT_NAMEandSERVICE_ACCOUNT_NAMESPACEwith the Kubernetes service account name and its namespace.export SERVICE_ACCOUNT_NAME="workload-identity-sa" # sample name; can be changed export SERVICE_ACCOUNT_NAMESPACE="default" # can be changed to namespace of your workload cat <<EOF | kubectl apply -f - apiVersion: v1 kind: ServiceAccount metadata: annotations: azure.workload.identity/client-id: ${USER_ASSIGNED_CLIENT_ID} name: ${SERVICE_ACCOUNT_NAME} namespace: ${SERVICE_ACCOUNT_NAMESPACE} EOFCreate the federated identity credential between the managed identity, service account issuer, and subject using the
az identity federated-credential createcommand.export FEDERATED_IDENTITY_NAME="aksfederatedidentity" # can be changed as needed az identity federated-credential create --name $FEDERATED_IDENTITY_NAME --identity-name $UAMI --resource-group $RESOURCE_GROUP --issuer ${AKS_OIDC_ISSUER} --subject system:serviceaccount:${SERVICE_ACCOUNT_NAMESPACE}:${SERVICE_ACCOUNT_NAME}Deploy a
SecretProviderClassusing thekubectl applycommand and the following YAML script.
The following parameters configure workload identity access:
usePodIdentity: Set to"false"when using workload identity.clientID: Set to${USER_ASSIGNED_CLIENT_ID}, the client ID of the user-assigned managed identity used for workload identity.cloudName: Optional. Leave empty to use the defaultAzurePublicCloudenvironment.objectType: Set to the type of Key Vault object to mount. Valid values aresecret,key, andcert.tenantId: Set to the tenant ID that contains the key vault.cat <<EOF | kubectl apply -f - # This is a SecretProviderClass example using workload identity to access your key vault apiVersion: secrets-store.csi.x-k8s.io/v1 kind: SecretProviderClass metadata: name: azure-kvname-wi # needs to be unique per namespace namespace: ${SERVICE_ACCOUNT_NAMESPACE} spec: provider: azure parameters: usePodIdentity: "false" clientID: "${USER_ASSIGNED_CLIENT_ID}" # Setting this to use workload identity keyvaultName: ${KEYVAULT_NAME} # Set to the name of your key vault cloudName: "" # [OPTIONAL for Azure] if not provided, the Azure environment defaults to AzurePublicCloud objects: | array: - | objectName: secret1 # Set to the name of your secret objectType: secret # object types: secret, key, or cert objectVersion: "" # [OPTIONAL] object versions, default to latest if empty - | objectName: key1 # Set to the name of your key objectType: key objectVersion: "" tenantId: "${KEYVAULT_TENANT_ID}" # The tenant ID of the key vault EOFNote
If you use
objectAliasinstead ofobjectName, update the YAML script to account for it.Note
In order for the
SecretProviderClassto function properly, make sure to populate your Azure Key Vault with secrets, keys, or certificates before referencing them in theobjectssection.
Deploy a sample pod using the
kubectl applycommand and the following YAML script.cat <<EOF | kubectl apply -f - # This is a sample pod definition for using SecretProviderClass and workload identity to access your key vault kind: Pod apiVersion: v1 metadata: name: busybox-secrets-store-inline-wi namespace: ${SERVICE_ACCOUNT_NAMESPACE} labels: azure.workload.identity/use: "true" spec: serviceAccountName: ${SERVICE_ACCOUNT_NAME} containers: - name: busybox image: registry.k8s.io/e2e-test-images/busybox:1.29-4 command: - "/bin/sleep" - "10000" volumeMounts: - name: secrets-store01-inline mountPath: "/mnt/secrets-store" readOnly: true volumes: - name: secrets-store01-inline csi: driver: secrets-store.csi.k8s.io readOnly: true volumeAttributes: secretProviderClass: "azure-kvname-wi" EOF
Validate Key Vault secrets with workload identity
After the pod starts, the mounted content at /mnt/secrets-store is available. Use the following commands to validate your secrets and print a test secret.
Show secrets held in the secrets store using the following command.
kubectl exec --namespace $SERVICE_ACCOUNT_NAMESPACE busybox-secrets-store-inline-wi -- ls /mnt/secrets-store/Display a secret in the store using the following command. This example command shows the test secret
secret1.kubectl exec --namespace $SERVICE_ACCOUNT_NAMESPACE busybox-secrets-store-inline-wi -- cat /mnt/secrets-store/secret1
Prerequisites for CSI Driver with managed identity
- Before you begin, make sure you finish the steps in Use the Azure Key Vault provider for Secrets Store CSI Driver in an Azure Kubernetes Service (AKS) cluster to enable the Azure Key Vault Secrets Store CSI Driver in your AKS cluster.
Access with managed identity
This method uses the user-assigned managed identity that AKS automatically creates when you enable the Azure Key Vault provider for Secrets Store CSI Driver. The identity is named azurekeyvaultsecretsprovider-xxxxx, is stored in the node resource group, and is assigned to the virtual machine scale set.
A Microsoft Entra managed identity enables an Azure resource or workload to authenticate to services that support Microsoft Entra authentication without storing credentials in code. Grant this identity the appropriate Key Vault data-plane permissions through Azure RBAC or access policies, and then use it in the following steps.
Configure managed identity
Access your key vault using the
az aks showcommand and the user-assigned managed identity created by the add-on. You should also retrieve the identity'sclientId, which you use in later steps when creating aSecretProviderClass.export RESOURCE_GROUP=<resource-group> export CLUSTER_NAME=<cluster-name> export KEYVAULT_NAME=<key-vault-name> export IDENTITY_OBJECT_ID=$(az aks show --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME --query addonProfiles.azureKeyvaultSecretsProvider.identity.objectId -o tsv) export USER_ASSIGNED_CLIENT_ID=$(az aks show --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME --query addonProfiles.azureKeyvaultSecretsProvider.identity.clientId -o tsv)Alternatively, you can create a new managed identity and assign it to your virtual machine (VM) scale set or to each VM instance in your availability set.
export USER_ASSIGNED_IDENTITY_NAME=<identity-name> az identity create --resource-group $RESOURCE_GROUP --name $USER_ASSIGNED_IDENTITY_NAME export IDENTITY_RESOURCE_ID=$(az identity show --resource-group $RESOURCE_GROUP --name $USER_ASSIGNED_IDENTITY_NAME --query id -o tsv) export IDENTITY_OBJECT_ID=$(az identity show --resource-group $RESOURCE_GROUP --name $USER_ASSIGNED_IDENTITY_NAME --query principalId -o tsv) export USER_ASSIGNED_CLIENT_ID=$(az identity show --resource-group $RESOURCE_GROUP --name $USER_ASSIGNED_IDENTITY_NAME --query clientId -o tsv)For a VM scale set-based cluster, assign the identity to the VM scale set.
az vmss identity assign --resource-group <node-resource-group> --name <agent-pool-vmss> --identities $IDENTITY_RESOURCE_IDFor an availability set-based cluster, assign the identity to each VM instance in the availability set.
az vm identity assign --resource-group <node-resource-group> --name <agent-pool-vm> --identities $IDENTITY_RESOURCE_IDCreate a role assignment that grants the identity permission to access the key vault secrets, access keys, and certificates using the
az role assignment createcommand.Important
- If you set your key vault with
--enable-rbac-authorizationand you're usingkeyorcerttype, assign theKey Vault Certificate Userrole. - If your key vault is set with
--enable-rbac-authorizationand you're usingsecrettype, assign theKey Vault Secrets Userrole. - If your key vault isn't set with
--enable-rbac-authorization, you can use theaz keyvault set-policycommand with the--key-permissions get,--certificate-permissions get, or--secret-permissions getparameter to create a key vault policy to grant access for keys, certificates, or secrets. For example:
az keyvault set-policy --name $KEYVAULT_NAME --key-permissions get --secret-permissions get --object-id $IDENTITY_OBJECT_IDexport KEYVAULT_SCOPE=$(az keyvault show --name $KEYVAULT_NAME --query id -o tsv) # Example commands for a key vault with Azure RBAC enabled using `key` and `secret` types az role assignment create --role "Key Vault Certificate User" --assignee-object-id $IDENTITY_OBJECT_ID --assignee-principal-type ServicePrincipal --scope $KEYVAULT_SCOPE az role assignment create --role "Key Vault Secrets User" --assignee-object-id $IDENTITY_OBJECT_ID --assignee-principal-type ServicePrincipal --scope $KEYVAULT_SCOPE- If you set your key vault with
Create a
SecretProviderClassusing the identity client ID. Make sure to use your own values for the objects to retrieve from your key vault.The following parameters configure user-assigned managed identity access:
usePodIdentity: Set to"false"when using managed identity.useVMManagedIdentity: Set to"true"to enable managed identity mode.userAssignedIdentityID: Set to the client ID of the user-assigned managed identity.tenantId: Set to the tenant ID that contains the key vault.
export KEYVAULT_TENANT_ID=$(az keyvault show --name $KEYVAULT_NAME --query properties.tenantId -o tsv) cat <<EOF > secretproviderclass.yaml # This is a SecretProviderClass example using user-assigned identity to access your key vault apiVersion: secrets-store.csi.x-k8s.io/v1 kind: SecretProviderClass metadata: name: azure-kvname-user-msi spec: provider: azure parameters: usePodIdentity: "false" useVMManagedIdentity: "true" # Set to true for using managed identity userAssignedIdentityID: ${USER_ASSIGNED_CLIENT_ID} # Set the client ID of the user-assigned managed identity to use keyvaultName: ${KEYVAULT_NAME} # Set to the name of your key vault cloudName: "" # [OPTIONAL for Azure] if not provided, the Azure environment defaults to AzurePublicCloud objects: | array: - | objectName: secret1 objectType: secret # object types: secret, key, or cert objectVersion: "" # [OPTIONAL] object versions, default to latest if empty - | objectName: key1 objectType: key objectVersion: "" tenantId: ${KEYVAULT_TENANT_ID} # The tenant ID of the key vault EOFNote
If you use
objectAliasinstead ofobjectName, make sure to update the YAML script.Note
In order for the
SecretProviderClassto function properly, make sure to populate your Azure Key Vault with secrets, keys, or certificates before referencing them in theobjectssection.Apply the
SecretProviderClassto your cluster using thekubectl applycommand.kubectl apply -f secretproviderclass.yamlCreate a pod manifest named
pod.yamlusing the following command.cat <<EOF > pod.yaml # This is a sample pod definition for using SecretProviderClass and the user-assigned identity to access your key vault kind: Pod apiVersion: v1 metadata: name: busybox-secrets-store-inline-user-msi spec: containers: - name: busybox image: registry.k8s.io/e2e-test-images/busybox:1.29-4 command: - "/bin/sleep" - "10000" volumeMounts: - name: secrets-store01-inline mountPath: "/mnt/secrets-store" readOnly: true volumes: - name: secrets-store01-inline csi: driver: secrets-store.csi.k8s.io readOnly: true volumeAttributes: secretProviderClass: "azure-kvname-user-msi" EOFApply the pod to your cluster using the
kubectl applycommand.kubectl apply -f pod.yaml
Validate Key Vault secrets with managed identity
After the pod starts, the mounted content at /mnt/secrets-store is available. Use the following commands to validate your secrets and print a test secret.
Show secrets held in the secrets store using the following command.
kubectl exec busybox-secrets-store-inline-user-msi -- ls /mnt/secrets-store/Display a secret in the store using the following command. This example command shows the test secret
secret1.kubectl exec busybox-secrets-store-inline-user-msi -- cat /mnt/secrets-store/secret1
Obtain certificates and keys
The Azure Key Vault design makes sharp distinctions between keys, secrets, and certificates. The certificate features of the Key Vault service are designed to make use of key and secret capabilities. When you create a key vault certificate, it creates an addressable key and secret with the same name. This key allows authentication operations, and the secret allows the retrieval of the certificate value as a secret.
A key vault certificate also contains public x509 certificate metadata. The key vault stores both the public and private components of your certificate in a secret. You can obtain each individual component by specifying the objectType in SecretProviderClass. The following table shows the objectType values you can specify in SecretProviderClass to retrieve different components of a key vault certificate and what each value returns:
objectType value |
Return value | Returns entire certificate chain |
|---|---|---|
key |
The public key, in Privacy Enhanced Mail (PEM) format. | N/A |
cert |
The certificate, in PEM format. | No |
secret |
The private key and certificate, in PEM format. | Yes |
Disable the add-on on existing clusters
Note
Before you disable the add-on, ensure that no SecretProviderClass is in use. Trying to disable the add-on while a SecretProviderClass exists results in an error.
Disable the Azure Key Vault provider for Secrets Store CSI Driver capability in an existing cluster using the az aks disable-addons command with the azure-keyvault-secrets-provider add-on.
az aks disable-addons --addons azure-keyvault-secrets-provider --resource-group myResourceGroup --name myAKSCluster
Note
When you disable the add-on, existing workloads should have no issues or see any updates in the mounted secrets. If the pod restarts or a new pod is created as part of scale-up event, the pod fails to start because the driver is no longer running.
Next steps
In this article, you learned how to create and provide an identity to access your Azure Key Vault. The Service Connector integration helps simplify the connection configuration for AKS workloads and Azure backing services. It securely handles authentication and network configurations and follows best practices for connecting to Azure services. For more information, see Use the Azure Key Vault provider for Secrets Store CSI Driver in an AKS cluster and the Service Connector introduction.
If you want to configure extra configuration options or perform troubleshooting, see Configuration options and troubleshooting resources for Azure Key Vault provider with Secrets Store CSI Driver in AKS.