AWS Security Hub · ES
ES.1: ES domains should encrypt at rest
Written and reviewed by Emnode · Last reviewed
What does AWS Security Hub ES.1 check?
ES.1 fails when a legacy Elasticsearch domain runs with encryption at rest switched off. Encryption at rest wraps the domain's indices, automated snapshots, swap files, and logs on its EBS volumes with an AWS KMS key.
Why does ES.1 matter?
An ES domain typically holds indexed logs, search corpora, or analytics data, frequently with PII like email addresses, IP addresses, or account identifiers buried in log lines. Without encryption, all of that sits on disk as plaintext, readable by anyone who reaches the underlying storage. Encryption at rest is a near-universal requirement across PCI DSS, HIPAA, SOC 2, and ISO 27001.
How do I fix ES.1?
- For a domain on Elasticsearch 6.7 or later, enable encryption in place: open the domain in the console, choose Actions then Edit security configuration, select Enable encryption of data at rest, pick a KMS key, and save. Or call UpdateDomainConfig with EncryptionAtRestOptions set to Enabled true and a KmsKeyId.
- If UltraWarm or cold storage is enabled, you cannot toggle encryption directly: move any UltraWarm or cold indices back to hot storage, disable UltraWarm/cold storage, enable encryption at rest, then re-enable UltraWarm/cold storage.
- For a pre-6.7 domain that cannot be enabled in place, snapshot it, create a new domain with encryption at rest enabled and a KMS key, restore the indices, cut traffic over, and decommission the unencrypted domain.
- Make encryption at rest a default in your domain provisioning templates so new domains are never created without it.
Remediation script · bash
# 1. Bulk-enable free SSE-SQS on every unencrypted queue in the region.
for q in $(aws sqs list-queues --query 'QueueUrls[]' --output text); do
state=$(aws sqs get-queue-attributes --queue-url $q \
--attribute-names KmsMasterKeyId SqsManagedSseEnabled --query 'Attributes' --output text)
[ -z "$state" ] && aws sqs set-queue-attributes --queue-url $q \
--attributes '{"SqsManagedSseEnabled":"true"}' && echo "encrypted $q"
done
# 2. High-throughput stream: SSE-KMS with a 5-minute data-key reuse window to keep KMS cost flat.
aws kinesis start-stream-encryption --stream-name payment-events \
--encryption-type KMS \
--key-id arn:aws:kms:us-east-1:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
# 3. Find unencrypted recovery points (Backup.1 reads IsEncrypted per recovery point, not per vault).
aws backup list-recovery-points-by-backup-vault --backup-vault-name prod-backups \
--query 'RecoveryPoints[?IsEncrypted==`false`].[RecoveryPointArn,ResourceType]' --output table
# 4. Confirm an at-rest Config rule is evaluating so regressions are caught automatically.
aws configservice describe-compliance-by-config-rule --config-rule-names sqs-queue-encrypted \
--query 'ComplianceByConfigRules[].Compliance.ComplianceType' Full walkthrough (console steps, edge cases and verification) in the lesson Encrypt other services at rest (queues, streams, logs, ML).
Is ES.1 a false positive?
There is no benign false positive here: a failing domain genuinely has encryption at rest disabled. Note that on Elasticsearch 6.7 or later this is an in-place fix (Edit security configuration / UpdateDomainConfig), not a mandatory rebuild; a full rebuild-and-migrate is only required for pre-6.7 domains.
More ES controls
- ES.2 A legacy Elasticsearch domain is publicly accessible
- ES.3 ES should encrypt node-to-node traffic
- ES.4 ES error logging to CW should be enabled
- ES.5 ES domains should have audit logging
- ES.6 ES domains should have >= 3 data nodes
- ES.7 ES domains should have >= 3 dedicated master nodes
- ES.8 ES should use latest TLS policy