AWS Security Hub · EKS
EKS.3: EKS clusters should use encrypted K8s secrets
Written and reviewed by Emnode · Last reviewed
What does AWS Security Hub EKS.3 check?
EKS.3 fails when a cluster does not use KMS envelope encryption for its Kubernetes secrets. By default secrets are only base64-encoded in etcd on top of the EBS encryption EKS already provides. Note that this control is being retired after August 10, 2026 and removed from all Security Hub CSPM standards: starting with Kubernetes 1.28, EKS clusters already protect secrets with envelope encryption by default, so it is largely moot for any modern cluster.
Why does EKS.3 matter?
base64 is a transport encoding, not encryption: anyone who can read a secret object decodes it instantly with `base64 -d`. A classic pen-test finding is read access to one namespace yielding the production database password in plain text. KMS envelope encryption layers real encryption over the secrets so a leaked etcd copy or API read does not hand over credentials.
How do I fix EKS.3?
- Audit the cluster's encryption config with the CLI to confirm whether a KMS key is associated for secrets.
- Enable it with a single `associate-encryption-config` call referencing your KMS key.
- Re-save existing secrets, since it only encrypts secrets written after it is enabled.
- Line up the KMS key policy with the cluster role; note this is a one-way operation that cannot be undone.
Remediation script · bash
# Enable rotation on an RDS-backed secret with the AWS-managed Lambda, 30-day cadence.
aws secretsmanager rotate-secret \
--secret-id prod/payments/db-master \
--rotation-lambda-arn arn:aws:lambda:eu-west-1:123456789012:function:SecretsManagerRDSPostgreSQLRotationSingleUser \
--rotation-rules AutomaticallyAfterDays=30
# Schedule deletion of stale secrets behind a recovery window (never force-delete in prod).
NOW=$(date -u +%FT%TZ)
for arn in $(aws secretsmanager list-secrets \
--query "SecretList[?LastAccessedDate<='$(date -u -d '90 days ago' +%FT%TZ)'].ARN" \
--output text); do
aws secretsmanager delete-secret --secret-id "$arn" --recovery-window-in-days 7
done
# Alarm so the next failed rotation pages a human, not the next audit.
aws cloudwatch put-metric-alarm \
--alarm-name secrets-rotation-failed --namespace AWS/Lambda --metric-name Errors \
--dimensions Name=FunctionName,Value=RotatePaymentsDbMaster \
--statistic Sum --period 3600 --evaluation-periods 1 \
--threshold 1 --comparison-operator GreaterThanOrEqualToThreshold \
--alarm-actions arn:aws:sns:us-east-1:123456789012:security-oncall Full walkthrough (console steps, edge cases and verification) in the lesson Manage secrets (rotation and hygiene).
Is EKS.3 a false positive?
EBS volume encryption is not the same thing; teams often assume it covers secrets. EKS.3 specifically wants KMS envelope encryption of the secret objects, and existing secrets stay readable until you re-save them. Also note that any cluster on Kubernetes 1.28 or higher already gets envelope encryption by default, so a manual `associate-encryption-config` step is only needed on older clusters or when you want your own customer-managed key.