🔐 Kubernetes Secrets Encryption at Rest: KMS Providers 2026
On this page
- Why Kubernetes Secrets Encryption at Rest Matters in 2026
- Architecture: How KMS Provider Encryption Works
- AWS EKS: Encryption with AWS KMS
- Azure AKS: Azure Key Vault Provider for Secrets Store CSI
- GCP GKE: Cloud KMS + CMEK Encryption
- HashiCorp Vault as KMS Provider
- Key Rotation and Audit Compliance
- When KMS Encryption Isn't Enough
- FAQs
By default, Kubernetes secrets are stored as base64-encoded plaintext in etcd. Any attacker with etcd access or a cluster-admin kubeconfig can exfiltrate every secret in the cluster — database credentials, API tokens, TLS certificates, and cloud provider keys. Encryption at rest changes this: the API server encrypts secrets before writing to etcd and decrypts on read, using a Key Management Service (KMS) provider. Without it, your Kubernetes cluster's security posture is fundamentally incomplete.
This is a technical guide — building on our VS Code zero-day token theft analysis and Docker Hub credential leak coverage — covering KMS provider setup, key rotation, audit logging, and compliance mapping for AWS EKS, Azure AKS, and GCP GKE.
Why Kubernetes Secrets Encryption at Rest Matters in 2026
The Verizon 2026 Data Breach Investigations Report found that 74% of cloud security incidents involved compromised credentials stored in plaintext. In Kubernetes environments, the attack path is well-documented: an attacker who gains read access to etcd (via a compromised node, backup exposure, or a misconfigured RBAC rule) reads every secret in the cluster with a single etcdctl get /registry/secrets --prefix command.
Encryption at rest closes this vector. The NIST SP 800-53 (SC-28) and CIS Kubernetes Benchmark (v1.9, section 4.2) both mandate encryption at rest for production clusters. The PCI DSS v4.0 requirement 3.4 explicitly requires encryption of stored account data — including the database credentials and API tokens stored as Kubernetes secrets.
Architecture: How KMS Provider Encryption Works
Kubernetes supports two encryption-at-rest models. The KMS v2 provider (GA since Kubernetes 1.28) is the production-grade option — it encrypts secrets using a Data Encryption Key (DEK) that the KMS provider generates and wraps with a Key Encryption Key (KEK) stored in an external KMS. The API server never holds the KEK; it only caches the DEK in memory for the duration of the encryption/decryption operation.
The KMS v2 gRPC protocol is a significant improvement over v1: it supports automatic key rotation at configurable intervals, status reporting via the Status method, and deterministic per-namespace key derivation that reduces KEK rewrap overhead during bulk operations.
When a new secret is created, the API server sends the plaintext to the KMS plugin via gRPC. The plugin calls the external KMS to generate a DEK, encrypts the secret with the DEK, stores the encrypted DEK as part of the resource metadata, and persists the ciphertext to etcd. On read, the API server sends the encrypted payload and wrapped DEK to the plugin, which calls the KMS to unwrap and decrypt.
AWS EKS: Encryption with AWS KMS
AWS EKS supports KMS encryption via the EncryptionConfig resource. The setup requires creating a KMS key with specific IAM permissions for the EKS cluster role:
# Create a symmetric KMS key
aws kms create-key --description "EKS Secrets Encryption Key" --key-usage ENCRYPT_DECRYPT --origin AWS_KMS --multi-region
# Grant the EKS cluster role permission to use the key
aws kms create-grant --key-id mrk-xxxxxxxx --grantee-principal arn:aws:iam::ACCOUNT:role/eks-cluster-role --operations "Encrypt" "Decrypt" "GenerateDataKey" "DescribeKey" "ReEncrypt*" "CreateGrant"
Once the KMS key is available, enable encryption at rest via the EKS console or CLI:
# Enable encryption on an existing cluster
eksctl enable encryption --cluster my-cluster --region us-east-1 --key-arn arn:aws:kms:us-east-1:ACCOUNT:key/mrk-xxxxxxxx
After enabling, existing secrets are NOT automatically re-encrypted. Trigger a re-encryption by performing a rolling secret update — the simplest approach is to patch the annotation on every namespace:
kubectl get secrets --all-namespaces -o json | jq '.items[].metadata.annotations["kubectl.kubernetes.io/last-applied-configuration"] = "rotate"' | kubectl apply -f -
NIST SP 800-57 compliance note: AWS KMS automatic key rotation (yearly by default) satisfies the cryptographic key rotation requirement. For stricter compliance, reduce the rotation period to 180 days using a custom key policy.
Azure AKS: Azure Key Vault Provider for Secrets Store CSI
Azure's approach is different: rather than encrypting etcd natively, AKS recommends the Azure Key Vault Provider for Secrets Store CSI Driver. This mounts secrets from Azure Key Vault as CSI volumes, keeping them out of etcd entirely:
# Enable the CSI driver add-on
az aks enable-addons --addons azure-keyvault-secrets-provider --name my-aks-cluster --resource-group my-rg
# Create a SecretProviderClass
cat <<EOF | kubectl apply -f -
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: my-keyvault-secrets
spec:
provider: azure
parameters:
usePodIdentity: false
useVMManagedIdentity: true
userAssignedIdentityID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
keyvaultName: my-keyvault
objects: |
array:
- |
objectName: db-password
objectType: secret
tenantId: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
EOF
Azure also supports etcd-level encryption via the --enable-encryption-at-host flag on AKS cluster creation, which encrypts secrets at the Azure managed-HSM level. This satisfies CIS Benchmark 4.2.1 (encrypt Kubernetes secrets at rest) for audit compliance.
For Enterprise and SOX-compliant workloads, Azure Key Vault with Managed HSM pools provides FIPS 140-2 Level 3 validated key storage — matching the security requirements for enterprise password management frameworks.
GCP GKE: Cloud KMS + CMEK Encryption
GKE supports KMS encryption via Customer-Managed Encryption Keys (CMEK). Create a Cloud KMS key ring and key, then enable encryption when creating or updating the cluster:
# Create a Cloud KMS key ring and key
gcloud kms keyrings create "cluster-keyring" --location "global"
gcloud kms keys create "cluster-key" --location "global" --keyring "cluster-keyring" --purpose "encryption"
# Grant the GKE service account access
gcloud kms keys add-iam-policy-binding "cluster-key" --location "global" --keyring "cluster-keyring" --member "serviceAccount:service-ACCOUNT_NUMBER@container-engine-robot.iam.gserviceaccount.com" --role "roles/cloudkms.cryptoKeyEncrypterDecrypter"
Enable application-layer secrets encryption on an existing GKE cluster:
gcloud container clusters update my-cluster --location us-central1 --enable-application-layer-secrets-encryption --kms-key "projects/PROJECT/locations/global/keyRings/cluster-keyring/cryptoKeys/cluster-key"
GKE's implementation uses envelope encryption: the API server generates a DEK, Cloud KMS wraps it, and the encrypted DEK is stored alongside the ciphertext in etcd. Key rotation is handled by Kubernetes automatically — the KMS plugin periodically generates new DEKs and re-wraps existing encrypted data.
For multi-cloud compliance, the ISO 27001:2022 control A.8.24 (use of cryptography) requires organizations to document and enforce encryption policies consistently across all cloud providers. GKE's CMEK model satisfies this when combined with a centralized key management policy.
HashiCorp Vault as KMS Provider
For multi-cloud or on-premise environments, HashiCorp Vault can serve as the KMS provider for Kubernetes encryption at rest. The Kubernetes Secrets Backend in Vault integrates with the KMS plugin via the Transit Secrets Engine:
# Enable the Transit engine in Vault
vault secrets enable transit
# Create an encryption key
vault write -f transit/keys/kubernetes-etcd
# Deploy the KMS plugin as a DaemonSet on each node
# (Vault provides the kms-plugin binary in their enterprise distribution)
The Vault-based approach gives you unified key management across all clusters and clouds — a single Vault cluster can serve as the KMS provider for EKS, AKS, GKE, and self-managed Kubernetes clusters simultaneously. This is particularly valuable for organizations running multi-region Kubernetes deployments that need consistent encryption policies across all environments.
The CIS Kubernetes Benchmark v1.9 recommends encryption at rest for all secrets (section 4.2). For the encryption at rest check specifically, the benchmark requires that the EncryptionConfiguration exists with at least one identity {} or aescbc {} provider. The KMS provider satisfies the requirement and adds external key management — a stronger posture than the embedded aescbc {} provider because the KEK never leaves the external KMS.
Key Rotation and Audit Compliance
Key rotation is the most commonly overlooked aspect of encryption at rest. Kubernetes does NOT automatically re-encrypt existing secrets when you rotate the KEK. Without a manual or automated rotation process, the old KEK continues to be usable indefinitely — defeating the purpose of rotation.
Rotation workflow for all providers:
- Create a new KEK in the KMS (KMS key version, Vault key version)
- Update the
EncryptionConfigurationto list the new KEK first, old KEK second - Restart the kube-apiserver pods to reload the configuration
- Generate new DEKs for each existing secret (a batch re-write using
kubectl get secrets -o json | kubectl apply -f -) - Remove the old KEK from the
EncryptionConfiguration - Verify all secrets are encrypted with the new KEK
For PCI DSS v4.0 requirement 3.6, maintain a documented key management procedure that covers generation, distribution, storage, rotation, and destruction of KEKs. The OWASP Kubernetes Security Cheat Sheet recommends quarterly key rotation as a baseline — yearly for low-sensitivity environments.
Audit logging recommendations:
- Enable Kubernetes audit logs for all
RequestResponsestages on thesecretsresource - Forward logs to a SIEM (Splunk, Elastic, Chronicle) with
objectRef.resource == "secrets"as a query filter - Monitor for
getoperations on secrets by non-system service accounts — use Falco or OPA/Gatekeeper to alert on suspicious secret access patterns - Enable CloudTrail (AWS) or Activity Logs (Azure) for KMS key usage tracking — correlate with Kubernetes audit logs for end-to-end visibility
When KMS Encryption Isn't Enough
Encryption at rest protects against etcd compromise, but it doesn't prevent secrets from being read by users or service accounts with secrets/get permissions. For fine-grained secret access control, combine encryption at rest with:
- Secrets Store CSI Driver — keeps secrets out of etcd entirely (Azure Key Vault provider, AWS Secrets Manager provider, GCP Secret Manager provider)
- Vault Sidecar Injector — injects secrets as volume mounts at pod creation time, never writing them to the cluster state store
- External Secrets Operator — syncs secrets from external providers into Kubernetes but keeps them encrypted at rest in the source of truth
- cert-manager with SPIRE — issues X.509 workload identities tied to SPIFFE IDs, eliminating the need for long-lived TLS certificate secrets
For the privacy-maximalist posture that securekeygenerator.com advocates, the recommended stack is: KMS encryption at rest (to satisfy compliance), Secrets Store CSI Driver (to minimize secret exposure in etcd), and Vault (for centralized key management). This three-layer approach protects against node compromise (CSI), etcd compromise (KMS), and KMS compromise (Vault's unseal mechanism).
FAQs
Does enabling encryption at rest affect performance?
Yes, but the impact is minimal. The KMS plugin caches the DEK in memory for encryption and decryption operations — typically sub-millisecond. The gRPC call to the KMS plugin adds 1-5ms per secret operation. For most clusters, the performance impact is below 3% on the API server's request latency. Bulk secret creation (thousands in one batch) will show higher latency due to KEK wrap operations.
What happens if the KMS is unavailable?
When the KMS is down, the API server cannot decrypt secrets — existing pods continue running because the kubelet caches secret values at mount time. However, new pod schedules that require secrets will fail, and kubectl get secrets API calls will return the encrypted ciphertext with a KMS plugin error. Kubernetes does not cache decrypted secrets; each read operation requires the KMS. Running two KMS instances with an active-passive failover pattern is recommended for production.
Does encryption at rest prevent unauthorized access through RBAC?
No. Encryption at rest protects against etcd-level attacks (backup exposure, node compromise, direct database read). It does NOT add RBAC enforcement or prevent a user with secrets get permissions from reading secrets. For RBAC-level protection, combine with OPA/Gatekeeper policies that restrict secret access to specific service accounts, and audit all secret reads through Kubernetes audit logs forwarded to your SIEM.
Is encryption at rest supported on all managed Kubernetes providers?
AWS EKS (via KMS), Azure AKS (via Key Vault CSI Driver), and GCP GKE (via Cloud KMS CMEK) all support encryption at rest. Self-managed Kubernetes can use HashiCorp Vault or a local KMS plugin. The CIS Benchmark v1.9 includes automated checks for each provider — eksctl get encryption (AWS), az aks show --query enableEncryptionAtHost (Azure), and gcloud container clusters describe --format (GCP).
Does re-encrypting old secrets require application downtime?
No. The re-encryption process — updating each secret's encrypted data in etcd — is a write operation that does not affect running pods. The kubelet caches secret values at pod creation time and does not re-read them on re-encryption. The process is safe to run during normal cluster operations and can be batched across all namespaces using a script or a Kubernetes CronJob.