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:
- Create an AKS cluster and an Azure Key Vault.
- 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. - Clean up resources.
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 Azure resources
Create a resource group using the
az group createcommand.az group create \ --name <resource-group-name> \ --location <location>Create an AKS cluster using the
az aks createcommand. The following example creates a single-node AKS cluster with managed identity enabled.az aks create \ --resource-group <resource-group-name> \ --name <cluster-name> \ --enable-managed-identity \ --node-count 1Connect to the cluster using the
az aks get-credentialscommand.az aks get-credentials \ --resource-group <resource-group-name> \ --name <cluster-name>Create an Azure key vault using the
az keyvault createcommand.az keyvault create \ --resource-group <resource-group-name> \ --name <key-vault-name> \ --location <location>Create a secret in the key vault using the
az keyvault secret setcommand.az keyvault secret set \ --vault-name <key-vault-name> \ --name <secret-name> \ --value <secret-value>
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 theazureKeyvaultSecretsProvideraddon. - 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
- 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 running on a pod uses to authenticate itself against other Azure services, such as workloads in software. The Secret Store CSI Driver integrates with native Kubernetes capabilities to federate with external identity providers.
In this security model, the AKS cluster acts as token issuer. Microsoft Entra ID then uses OIDC to discover public signing keys and verify the authenticity of the service account token before exchanging it for a Microsoft Entra token. For your workload to exchange a service account token projected to its volume for a Microsoft Entra token, you need the Azure Identity client library in the Azure SDK or the Microsoft Authentication Library (MSAL)
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 IDENTITY_TENANT=$(az aks show --name $CLUSTER_NAME --resource-group $RESOURCE_GROUP --query identity.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 your key vault is set with
--enable-rbac-authorizationand you're usingkeyorcertificatetype, 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 --object-id $IDENTITY_OBJECT_IDexport KEYVAULT_SCOPE=$(az keyvault show --name $KEYVAULT_NAME --query id -o tsv) # Example command for key vault with Azure RBAC enabled using `key` type az role assignment create --role "Key Vault Certificate User" --assignee $USER_ASSIGNED_CLIENT_ID --scope $KEYVAULT_SCOPE- If your key vault is set 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_ISSUEREstablish a federated identity credential between the Microsoft Entra application, service account issuer, and subject. Get the object ID of the Microsoft Entra application using the following commands. Make sure to update the values for
serviceAccountNameandserviceAccountNamespacewith 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.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 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: "${IDENTITY_TENANT}" # 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 labels: azure.workload.identity/use: "true" spec: serviceAccountName: "workload-identity-sa" 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
Prerequisites for CSI Driver
- 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
A Microsoft Entra Managed ID is an identity that an administrator uses to authenticate themselves against other Azure services. The managed identity uses Azure RBAC to federate with external identity providers.
In this security model, you can grant access to your cluster's resources to team members or tenants sharing a managed role. The role is checked for scope to access the keyvault and other credentials. When you enabled the Azure Key Vault provider for Secrets Store CSI Driver on your AKS Cluster, it created a user identity.
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.az aks show --resource-group <resource-group> --name <cluster-name> --query addonProfiles.azureKeyvaultSecretsProvider.identity.objectId -o tsv az aks show --resource-group <resource-group> --name <cluster-name> --query addonProfiles.azureKeyvaultSecretsProvider.identity.clientId -o tsvAlternatively, 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 using the following commands.
az identity create --resource-group <resource-group> --name <identity-name> az vmss identity assign --resource-group <resource-group> --name <agent-pool-vmss> --identities <identity-resource-id> az vm identity assign --resource-group <resource-group> --name <agent-pool-vm> --identities <identity-resource-id> az identity show --resource-group <resource-group> --name <identity-name> --query 'clientId' -o tsvCreate 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 your key vault is set with
--enable-rbac-authorizationand you're usingkeyorcertificatetype, 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 --object-id $IDENTITY_OBJECT_IDexport IDENTITY_OBJECT_ID="$(az identity show --resource-group <resource-group> --name <identity-name> --query 'principalId' -o tsv)" export KEYVAULT_SCOPE=$(az keyvault show --name <key-vault-name> --query id -o tsv) # Example command for key vault with Azure RBAC enabled using `key` type az role assignment create --role "Key Vault Certificate User" --assignee $USER_ASSIGNED_CLIENT_ID --scope $KEYVAULT_SCOPE- If your key vault is set with
Create a
SecretProviderClassusing the following YAML. Make sure to use your own values foruserAssignedIdentityID,keyvaultName,tenantId, and the objects to retrieve from your key vault.# 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: <client-id> # Set the clientID of the user-assigned managed identity to use keyvaultName: <key-vault-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: <tenant-id> # The tenant ID of the key vaultNote
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 using the following 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"Apply the pod to your cluster using the
kubectl applycommand.kubectl apply -f pod.yaml
Validate Key Vault secrets
After the pod starts, the mounted content at the volume path specified in your deployment YAML 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
ExampleSecret.kubectl exec busybox-secrets-store-inline-user-msi -- cat /mnt/secrets-store/ExampleSecret
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 which objects map to the various resources associated with your certificate:
| Object | 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 addon 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.
Azure Kubernetes Service