Skip to main content

Kubernetes Secrets Are Encrypted Using CMKs Managed In AWS

More Info:

Enable envelope encryption of Kubernetes secrets using a customer master key (CMK) in AWS KMS so that secrets are encrypted at rest with a customer-managed key.

Risk Level

High

Address

Security

Compliance Standards

  • CIS EKS

Triage and Remediation

Remediation

Manual Steps
  1. Identify the cluster and its region

    • From any machine with AWS CLI configured, list clusters and their regions:
      aws eks list-clusters --region us-east-1
      aws eks list-clusters --region us-west-2
      # repeat for other regions you use
    • Note the exact clusterName and region you need to assess.
  2. Check if envelope encryption with a CMK is enabled for the cluster

    • On any machine with AWS CLI access, run:
      aws eks describe-cluster \
      --name your-cluster-name \
      --region your-region \
      --query 'cluster.encryptionConfig' \
      --output json
    • If the result is null or an empty list [], Kubernetes secrets are not encrypted with a CMK.
    • If it returns an array, confirm there is an entry with resources containing "secrets" and a non-empty provider.keyArn.
  3. Verify the KMS key configuration and ownership

    • Still on any machine with AWS CLI access, for each keyArn reported above, get details:
      aws kms describe-key \
      --key-id arn:aws:kms:your-region:your-account-id:key/your-key-id \
      --region your-region
    • Confirm:
      • KeyState is Enabled.
      • KeyManager is CUSTOMER (indicates a customer-managed CMK, not AWS-managed).
      • The key policy allows the EKS cluster IAM role or node IAM role to use the key.
  4. Decide compliance status

    • Cluster is compliant with this control if:
      • encryptionConfig includes resources: ["secrets"] (or includes secrets), and
      • provider.keyArn refers to an Enabled CMK with KeyManager: CUSTOMER.
    • Cluster is non-compliant if:
      • encryptionConfig is missing, or
      • secrets is not listed as a resource, or
      • The key is AWS-managed (not customer-managed), or
      • The key is disabled.
  5. Plan remediation for a non-compliant cluster (high-level)

    • Because EKS only allows enabling secrets encryption with a CMK at cluster creation time, you cannot turn this on for an existing cluster in-place.
    • For non-compliant clusters, plan to:
      • Create a new CMK in AWS KMS with appropriate key policy.
      • Recreate the EKS cluster with secrets encryption configured to use that CMK.
      • Migrate workloads, data, and secrets from the old cluster to the new, then decommission the old cluster.
  6. Document evidence and remediation decision

    • Save the output of the describe-cluster and describe-key commands as audit evidence.
    • Record for each cluster:
      • Whether secrets encryption with a customer-managed CMK is enabled.
      • Which CMK is used and its status.
      • Your remediation plan and target timeline if the cluster is non-compliant.
Using kubectl

kubectl cannot configure EKS secrets envelope encryption with AWS KMS CMKs because this setting is part of the managed control-plane configuration at cluster creation time. To remediate this finding, use the AWS console/CLI/IaC as described in the Manual Steps section to create a new cluster with secrets encryption enabled.

Automation
#!/usr/bin/env bash
#
# Report whether EKS clusters have Kubernetes Secrets encrypted with a
# customer-managed AWS KMS key (CMK).
#
# REQUIREMENTS:
# - AWS CLI v2 configured with sufficient permissions
# - jq
#
# SCOPE:
# - This runs from any machine with AWS CLI access.
# - It inspects all EKS clusters in the specified region(s).

set -euo pipefail

REGIONS="${*:-}"

if [ -z "$REGIONS" ]; then
echo "Usage: $0 <region-1> [region-2] ..."
echo "Example: $0 us-east-1 us-west-2"
exit 1
fi

for REGION in $REGIONS; do
echo "=== Region: $REGION ==="
CLUSTERS=$(aws eks list-clusters --region "$REGION" --output json | jq -r '.clusters[]?')

if [ -z "$CLUSTERS" ]; then
echo " No EKS clusters found."
continue
fi

for CLUSTER in $CLUSTERS; do
echo " Cluster: $CLUSTER"

DESC=$(aws eks describe-cluster --region "$REGION" --name "$CLUSTER" --output json)

# Extract encryption config for secrets provider
ENC_CFG=$(echo "$DESC" | jq -c '.cluster.encryptionConfig[]? | select(.resources[]? == "secrets")')

if [ -z "$ENC_CFG" ]; then
echo " status: NON-COMPLIANT - no encryptionConfig for secrets (no KMS envelope encryption)."
continue
fi

# There may be multiple keyArn entries; report them all
KEY_ARNS=$(echo "$ENC_CFG" | jq -r '.provider.keyArn // empty')

if [ -z "$KEY_ARNS" ]; then
echo " status: NON-COMPLIANT - secrets encryptionConfig present but no KMS keyArn found."
continue
fi

# For each key, determine whether it is customer-managed or AWS-managed
while IFS= read -r KEY_ARN; do
if [ -z "$KEY_ARN" ]; then
continue
fi

# Describe the KMS key
KEY_DESC=$(aws kms describe-key --region "$REGION" --key-id "$KEY_ARN" --output json 2>/dev/null || true)

if [ -z "$KEY_DESC" ]; then
echo " status: REVIEW - KMS key $KEY_ARN not describable (check permissions/existence)."
continue
fi

KEY_MANAGER=$(echo "$KEY_DESC" | jq -r '.KeyMetadata.KeyManager')
KEY_STATE=$(echo "$KEY_DESC" | jq -r '.KeyMetadata.KeyState')
KEY_USAGE=$(echo "$KEY_DESC" | jq -r '.KeyMetadata.KeyUsage')

# KeyManager:
# - 'CUSTOMER' => customer-managed CMK (desired)
# - 'AWS' => AWS-managed key (not compliant with CMK requirement)
if [ "$KEY_MANAGER" = "CUSTOMER" ] && [ "$KEY_STATE" = "Enabled" ] && [ "$KEY_USAGE" = "ENCRYPT_DECRYPT" ]; then
echo " status: COMPLIANT - secrets encrypted with CUSTOMER-managed CMK:"
echo " keyArn: $KEY_ARN"
echo " keyState: $KEY_STATE"
echo " keyUsage: $KEY_USAGE"
else
echo " status: NON-COMPLIANT - secrets encryption uses non-CUSTOMER CMK or unusable key:"
echo " keyArn: $KEY_ARN"
echo " keyManager:$KEY_MANAGER (expected: CUSTOMER)"
echo " keyState: $KEY_STATE (expected: Enabled)"
echo " keyUsage: $KEY_USAGE (expected: ENCRYPT_DECRYPT)"
fi

done <<< "$KEY_ARNS"

done
done

Explanation of output to review:

  • status: COMPLIANT

    • Secrets encryption is enabled for the cluster, and the KMS key used is customer-managed (KeyManager is CUSTOMER), enabled, and usable for ENCRYPT_DECRYPT.
  • status: NON-COMPLIANT - no encryptionConfig for secrets

    • The cluster has no envelope encryption configured for Kubernetes Secrets. This violates the control.
  • status: NON-COMPLIANT - secrets encryptionConfig present but no KMS keyArn found

    • Misconfigured cluster; manually inspect in the AWS console or via aws eks describe-cluster.
  • status: NON-COMPLIANT - secrets encryption uses non-CUSTOMER CMK or unusable key

    • Secrets encryption exists, but:
      • Uses an AWS-managed key (KeyManager: AWS), or
      • Uses a disabled key (KeyState not Enabled), or
      • Uses a key not configured for ENCRYPT_DECRYPT.
    • This does not satisfy the requirement for a customer-managed CMK.
  • status: REVIEW - KMS key ... not describable

    • The script cannot determine the key details. Check IAM permissions and the key’s region/account, then review manually.

Because this control is marked MANUAL and encryption can only be enabled at cluster creation time, this script is for visibility and review; bringing non-compliant clusters into compliance requires recreating them with Secrets Encryption configured to use a customer-managed KMS key.