|
| 1 | +--- |
| 2 | +title: Configure encryption for Azure Elastic SAN volumes |
| 3 | +description: Learn how to configure Azure Elastic SAN encryption with customer-managed keys (CMK) for volumes provisioned via Azure Container Storage by using Azure CLI. |
| 4 | +author: saurabh0501 |
| 5 | +ms.service: azure-container-storage |
| 6 | +ms.date: 01/28/2026 |
| 7 | +ms.author: saurabsharma |
| 8 | +ms.topic: overview |
| 9 | +# Customer intent: As a cloud administrator, I want to configure customer-managed keys for Azure Elastic SAN encryption when used with Azure Container Storage, so that my data management practices meet compliance requirements. |
| 10 | +--- |
| 11 | + |
| 12 | +# Configure encryption for Azure Elastic SAN |
| 13 | + |
| 14 | +All data written to an Elastic SAN volume is encrypted at rest with a data encryption key (DEK). Azure uses [envelope encryption](../../security/fundamentals/encryption-atrest.md#envelope-encryption-with-a-key-hierarchy) to encrypt the DEK with a key encryption key (KEK). By default, Azure uses a platform-managed KEK. You can use a customer-managed key (CMK) stored in Azure Key Vault. |
| 15 | + |
| 16 | +This article shows how to configure encryption for an Elastic SAN volume group by using a CMK in Azure Key Vault. |
| 17 | + |
| 18 | +## Prerequisites |
| 19 | + |
| 20 | +- This article requires the latest version of the Azure CLI. See [How to install the Azure CLI](/cli/azure/install-azure-cli). If you use Azure Cloud Shell, the latest version is already installed. If you run commands locally, use an account with administrative privileges. |
| 21 | +- This article assumes you installed Azure Container Storage version 2.1.0 or later on your Azure Kubernetes Service (AKS) cluster. |
| 22 | + |
| 23 | +## Configure the key vault |
| 24 | + |
| 25 | +You can use a new or existing key vault to store customer-managed keys. The encrypted resource and the key vault can be in different regions or subscriptions in the same Microsoft Entra ID tenant. To learn more, see [Azure Key Vault Overview](/azure/key-vault/general/overview) and [What is Azure Key Vault?](/azure/key-vault/general/basic-concepts). |
| 26 | + |
| 27 | +Encryption with customer-managed keys requires that both soft delete and purge protection are enabled for the key vault. Soft delete is enabled by default when you create a new key vault and can't be disabled. You can enable purge protection when you create the key vault or after it is created. Azure Elastic SAN encryption supports RSA keys of sizes 2048, 3072, and 4096. |
| 28 | + |
| 29 | +Azure Key Vault supports authorization with Azure role-based access control (Azure RBAC). Microsoft recommends Azure RBAC over key vault access policies. For more information, see [Provide access to Key Vault keys, certificates, and secrets with Azure role-based access control](/azure/key-vault/general/rbac-guide). |
| 30 | + |
| 31 | +Prepare a key vault for your volume group KEKs: |
| 32 | + |
| 33 | +> [!div class="checklist"] |
| 34 | +> - Create a new key vault with soft delete and purge protection enabled, or enable purge protection for an existing key vault. |
| 35 | +> - Create or assign an Azure RBAC role that grants key permissions: get, wrapKey, and unwrapKey. |
| 36 | +
|
| 37 | +To create a new key vault using Azure CLI, call [az keyvault create](/cli/azure/keyvault#az-keyvault-create). The following example creates a new key vault with soft delete and purge protection enabled. The key vault permission model uses Azure RBAC. Replace the placeholder values in brackets with your own values. |
| 38 | + |
| 39 | +```azurecli-interactive |
| 40 | +az keyvault create --name <key-vault-name> --resource-group <resource-group-name> --location <location> --enable-purge-protection --retention-days 7 |
| 41 | +``` |
| 42 | + |
| 43 | +To enable purge protection on an existing key vault, see [Azure Key Vault recovery overview](/azure/key-vault/general/key-vault-recovery?tabs=azure-cli). |
| 44 | + |
| 45 | +## Create a user-assigned managed identity and grant access to the key vault |
| 46 | + |
| 47 | +Create a user-assigned managed identity in the managed resource group of your AKS cluster: |
| 48 | + |
| 49 | +```azurecli |
| 50 | +az identity create --name <identity-name> --resource-group <node-resource-group> |
| 51 | +``` |
| 52 | + |
| 53 | +Get the identity IDs and store them in variables: |
| 54 | + |
| 55 | +```azurecli |
| 56 | +uai_id=$(az identity show --name <identity-name> --resource-group <node-resource-group> --query id -o tsv) |
| 57 | +uai_principal_id=$(az identity show --ids "$uai_id" --query principalId -o tsv) |
| 58 | +``` |
| 59 | + |
| 60 | +When you enable customer-managed encryption keys for an Elastic SAN volume group, you must specify a managed identity to authorize access to the key vault that contains the key. |
| 61 | + |
| 62 | +If your key vault uses access policies, set the key permissions for the managed identity. If your vault uses Azure RBAC, assign an equivalent role instead. |
| 63 | + |
| 64 | +```azurecli |
| 65 | +az keyvault set-policy --name <key-vault-name> --resource-group <resource-group-name> --object-id $uai_principal_id --key-permissions get wrapKey unwrapKey |
| 66 | +``` |
| 67 | + |
| 68 | +## Add a key |
| 69 | + |
| 70 | +Before you add the key, make sure you have the **Key Vault Crypto Officer** role. |
| 71 | + |
| 72 | +Get the vault URI and store it in a variable: |
| 73 | + |
| 74 | +```azurecli |
| 75 | +vault_uri=$(az keyvault show --name <key-vault-name> --resource-group <resource-group-name> --query "properties.vaultUri" -o tsv) |
| 76 | +``` |
| 77 | + |
| 78 | +Create an encryption key: |
| 79 | + |
| 80 | +```azurecli |
| 81 | +az keyvault key create --name <key-name> --vault-name <key-vault-name> --kty RSA --size 2048 |
| 82 | +``` |
| 83 | + |
| 84 | +## Create a StorageClass |
| 85 | + |
| 86 | +Create a YAML manifest file such as `storageclass.yaml`. Use the names and variables from the previous steps. |
| 87 | + |
| 88 | +```yaml |
| 89 | +apiVersion: storage.k8s.io/v1 |
| 90 | +kind: StorageClass |
| 91 | +metadata: |
| 92 | + name: azuresan-encrypted |
| 93 | +provisioner: san.csi.azure.com |
| 94 | +reclaimPolicy: Delete |
| 95 | +volumeBindingMode: Immediate |
| 96 | +allowVolumeExpansion: true |
| 97 | +parameters: |
| 98 | + encryption.keyvaulturi: "${vault_uri}" |
| 99 | + encryption.keyname: <key-name> |
| 100 | + encryption.identity: "${uai_id}" |
| 101 | +``` |
| 102 | +
|
| 103 | +Apply the manifest to create the StorageClass. |
| 104 | +
|
| 105 | +```azurecli |
| 106 | +kubectl apply -f storageclass.yaml |
| 107 | +``` |
| 108 | + |
| 109 | +## Create a persistent volume claim |
| 110 | + |
| 111 | +Create a YAML manifest file such as `acstor-pvc.yaml`. |
| 112 | + |
| 113 | +```yaml |
| 114 | +apiVersion: v1 |
| 115 | +kind: PersistentVolumeClaim |
| 116 | +metadata: |
| 117 | + name: pvc-san-encrypted |
| 118 | +spec: |
| 119 | + volumeMode: Filesystem |
| 120 | + accessModes: |
| 121 | + - ReadWriteOnce |
| 122 | + resources: |
| 123 | + requests: |
| 124 | + storage: 1Gi |
| 125 | + storageClassName: azuresan-encrypted |
| 126 | +``` |
| 127 | +
|
| 128 | +Apply the manifest to create the PVC. |
| 129 | +
|
| 130 | +```azurecli |
| 131 | +kubectl apply -f acstor-pvc.yaml |
| 132 | +``` |
| 133 | + |
| 134 | +## Deploy a pod |
| 135 | + |
| 136 | +Create a YAML manifest file such as `acstor-pod.yaml`. |
| 137 | + |
| 138 | +```yaml |
| 139 | +apiVersion: v1 |
| 140 | +kind: Pod |
| 141 | +metadata: |
| 142 | + name: pod-san-encrypted |
| 143 | +spec: |
| 144 | + nodeSelector: |
| 145 | + kubernetes.io/os: linux |
| 146 | + containers: |
| 147 | + - name: pod-san-encrypted |
| 148 | + image: mcr.microsoft.com/azurelinux/busybox:1.36 |
| 149 | + command: |
| 150 | + - "/bin/sh" |
| 151 | + - "-c" |
| 152 | + - set -euo pipefail; trap exit TERM; while true; do echo "$(date)" >> /mnt/san/outfile; sleep 1; done |
| 153 | + volumeMounts: |
| 154 | + - name: persistent-storage-encrypted |
| 155 | + mountPath: /mnt/san |
| 156 | + volumes: |
| 157 | + - name: persistent-storage-encrypted |
| 158 | + persistentVolumeClaim: |
| 159 | + claimName: pvc-san-encrypted |
| 160 | +``` |
| 161 | +
|
| 162 | +Apply the manifest to deploy the pod. |
| 163 | +
|
| 164 | +```azurecli |
| 165 | +kubectl apply -f acstor-pod.yaml |
| 166 | +``` |
| 167 | + |
| 168 | +You should see output similar to the following: |
| 169 | + |
| 170 | +```output |
| 171 | +pod/pod-san-encrypted created |
| 172 | +``` |
| 173 | + |
| 174 | +## Verify encryption on the volume group |
| 175 | + |
| 176 | +Get the Elastic SAN volume handle from the persistent volume (PV): |
| 177 | + |
| 178 | +```azurecli |
| 179 | +kubectl get pv <pv-name> -o jsonpath='{.spec.csi.volumeHandle}' |
| 180 | +``` |
| 181 | + |
| 182 | +Use the resource group, Elastic SAN name, and volume group name from the volume handle to get volume group details: |
| 183 | + |
| 184 | +```azurecli |
| 185 | +az elastic-san volume-group show --resource-group <resource-group-name> --elastic-san-name <elastic-san-name> --name <volume-group-name> --output json |
| 186 | +``` |
| 187 | + |
| 188 | +Validate read and write operations on the encrypted volume: |
| 189 | + |
| 190 | +```azurecli |
| 191 | +kubectl exec pod-san-encrypted -- sh -c "echo 'testing encrypted storage' > /mnt/san/test-encryption.txt && cat /mnt/san/test-encryption.txt" |
| 192 | +``` |
| 193 | + |
| 194 | +## Next steps |
| 195 | + |
| 196 | +- [What is Azure Elastic SAN?](../elastic-san/elastic-san-introduction.md) |
| 197 | +- [Manage customer keys for Azure Elastic SAN data encryption](../elastic-san/elastic-san-encryption-manage-customer-keys.md) |
0 commit comments