Kubernetes Secrets Are Encrypted Using Customer Master Keys
More Info:
Where etcd encryption is used, appropriate providers should be configured.
Risk Level
Medium
Address
Security
Compliance Standards
- APRA CPS 234 (Australia)
- BSI C5 (Germany)
- Brazil LGPD
- CCPA / CPRA (California)
- CIS Critical Security Controls v8
- CIS EKS
- CMMC 2.0
- CSA Cloud Controls Matrix v4
- DPDPA
- Digital Operational Resilience Act (EU)
- ISO/IEC 27017
- ISO/IEC 27018
- ISO/IEC 27701
- KSA PDPL
- MAS Technology Risk Management (Singapore)
- MITRE ATT&CK (Cloud)
- NIS2 Directive
- NIST SP 800-171
- NYDFS 23 NYCRR 500
- SWIFT Customer Security Controls Framework
- Sarbanes-Oxley IT General Controls
- UK NCSC Cyber Assessment Framework
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
Identify the cluster and region
- On any machine with AWS CLI access, list clusters and pick the target name and region:
aws eks list-clusters --region us-east-1aws eks describe-cluster --name <CLUSTER_NAME> --region <REGION>
- On any machine with AWS CLI access, list clusters and pick the target name and region:
-
Check if KMS encryption is enabled and which key is used
- On any machine with AWS CLI access, run:
aws eks describe-cluster \--name <CLUSTER_NAME> \--region <REGION> \--query 'cluster.encryptionConfig' \--output json
- Review the output: ensure
resourcesincludes"secrets"and thatprovider.keyArnpoints to the intended customer-managed KMS key (not just an AWS-managed default, if your policy requires CMKs).
- On any machine with AWS CLI access, run:
-
Review the KMS key configuration and key policy
- On any machine with AWS CLI access, get key details:
aws kms describe-key --key-id <KEY_ARN> --region <REGION>aws kms get-key-policy \--key-id <KEY_ARN> \--policy-name default \--region <REGION> \--output json
- Confirm the key is customer-managed, enabled, in the correct account, and the key policy allows the EKS cluster’s IAM role (or node roles, per your design) to use it for encryption/decryption.
- On any machine with AWS CLI access, get key details:
-
Decide remediation approach (replacement, recreation, or accept risk)
- If
encryptionConfigis empty, does not include"secrets", or uses an incorrect key:- Document that etcd secrets are not protected by the desired CMK.
- Decide whether to:
- Recreate the cluster with Secrets Encryption enabled and the correct CMK, then migrate workloads; or
- Create a new, compliant cluster and gradually cut over; or
- Accept/temporarily waive the risk with a documented exception.
- If
-
Implement remediation via cloud/IaC (for new or replacement clusters)
- For a new or replacement cluster using AWS CLI, specify encryption with your CMK:
aws eks create-cluster \--name <NEW_CLUSTER_NAME> \--region <REGION> \--role-arn <EKS_SERVICE_ROLE_ARN> \--resources-vpc-config subnetIds=<SUBNET_IDS>,securityGroupIds=<SG_IDS> \--encryption-config '[{"resources":["secrets"],"provider":{"keyArn":"<KMS_KEY_ARN>"}}]'
- If using CloudFormation/Terraform, configure the
encryptionConfig/encryption_configblock withresources = ["secrets"]andprovider.keyArn = <KMS_KEY_ARN>and deploy the new cluster.
- For a new or replacement cluster using AWS CLI, specify encryption with your CMK:
-
Verify the final state
- After creating or migrating to the compliant cluster, re-run:
aws eks describe-cluster \--name <CLUSTER_NAME> \--region <REGION> \--query 'cluster.encryptionConfig' \--output json
- Confirm that
resourcesincludes"secrets"andprovider.keyArnmatches the intended customer-managed KMS CMK.
- After creating or migrating to the compliant cluster, re-run:
Using kubectl
kubectl cannot configure EKS secrets encryption or modify the kube-apiserver encryption-provider settings; this must be done via the EKS control plane configuration at cluster creation time using the AWS console/CLI/IaC. Refer to the Manual Steps section for how to review current settings and plan remediation (which will typically require recreating the cluster with Secrets Encryption enabled).
Automation
#!/usr/bin/env bash
#
# Report EKS secrets encryption status for one or more clusters.
#
# REQUIREMENTS (run on: any machine with AWS CLI and kubectl access):
# - aws CLI v2 configured with permissions to describe EKS clusters
# - jq installed
#
# USAGE:
# ./check-eks-secrets-encryption.sh REGION CLUSTER1 [CLUSTER2 ...]
#
# NOTES:
# - This does NOT change anything; it only reports current state.
# - For a given cluster, **problems** are:
# * "encryptionConfig: []" → no EKS‑managed secrets encryption
# * "resources: []" or missing "secrets" in resources
# * "keyArn: null" → no CMK configured
# * KMS key not enabled / cannot be described
set -euo pipefail
if [ "$#" -lt 2 ]; then
echo "Usage: $0 REGION CLUSTER1 [CLUSTER2 ...]" >&2
exit 1
fi
REGION="$1"
shift
if ! command -v aws >/dev/null 2>&1; then
echo "ERROR: aws CLI not found in PATH" >&2
exit 2
fi
if ! command -v jq >/dev/null 2>&1; then
echo "ERROR: jq not found in PATH" >&2
exit 2
fi
echo "Region: ${REGION}"
echo
for CLUSTER in "$@"; do
echo "==== Cluster: ${CLUSTER} ===="
# 1. Describe the cluster's encryption config from the EKS control plane
if ! DESC_JSON=$(aws eks describe-cluster \
--name "${CLUSTER}" \
--region "${REGION}" 2>/dev/null); then
echo " ERROR: unable to describe cluster via AWS API (check name/permissions)."
echo
continue
fi
# Extract encryption config
ENC_JSON=$(echo "${DESC_JSON}" | jq -c '.cluster.encryptionConfig // []')
# Human‑readable summary
echo " EKS encryptionConfig (control plane view):"
echo "${ENC_JSON}" | jq '.'
# Simple evaluations
ENC_COUNT=$(echo "${ENC_JSON}" | jq 'length')
if [ "${ENC_COUNT}" -eq 0 ]; then
echo " ISSUE: No EKS secrets encryption configured (encryptionConfig is empty)."
else
# For each provider entry, check secrets + keyArn
echo "${ENC_JSON}" | jq -c '.[]' | nl -ba | while read -r IDX LINE; do
RESOURCES=$(echo "${LINE}" | jq -r '.resources // [] | join(",")')
KEY_ARN=$(echo "${LINE}" | jq -r '.provider.keyArn // empty')
echo " Provider #${IDX}:"
echo " resources: ${RESOURCES:-<none>}"
echo " keyArn: ${KEY_ARN:-<none>}"
if [ -z "${RESOURCES}" ]; then
echo " ISSUE: resources list empty; 'secrets' not covered."
elif ! echo "${RESOURCES}" | tr ',' '\n' | grep -qx 'secrets'; then
echo " ISSUE: 'secrets' not present in resources; secrets not encrypted by this provider."
fi
if [ -z "${KEY_ARN}" ]; then
echo " ISSUE: keyArn is missing; CMK not configured correctly."
else
# 2. Describe the CMK status from KMS
if KEY_DESC=$(aws kms describe-key \
--key-id "${KEY_ARN}" \
--region "${REGION}" 2>/dev/null); then
KEY_STATE=$(echo "${KEY_DESC}" | jq -r '.KeyMetadata.KeyState')
KEY_MANAGER=$(echo "${KEY_DESC}" | jq -r '.KeyMetadata.KeyManager')
echo " KMS key state: ${KEY_STATE}"
echo " KMS key manager: ${KEY_MANAGER}"
if [ "${KEY_STATE}" != "Enabled" ]; then
echo " ISSUE: KMS key is not Enabled (current state: ${KEY_STATE})."
fi
if [ "${KEY_MANAGER}" != "CUSTOMER" ]; then
echo " ISSUE: KMS key is not a customer managed CMK (KeyManager=${KEY_MANAGER})."
fi
else
echo " ISSUE: unable to describe KMS key (check IAM or key exists)."
fi
fi
done
fi
echo
done
How to interpret the output
Run (from any machine with AWS CLI access):
./check-eks-secrets-encryption.sh us-east-1 my-prod-cluster my-dev-cluster
Indicators of a problem for a given cluster:
encryptionConfig: []or printed as[]- Any provider with:
resources: <none>orresourcesnot includingsecretskeyArn: <none>- KMS key state not
Enabled - KMS
KeyManagernotCUSTOMER(i.e., not a customer-managed CMK)
This script only reports; remediation requires recreating or reconfiguring the cluster with Secrets Encryption enabled using a customer-managed KMS CMK.