Skip to main content
emnode
Compliance Medium severity

AWS Security Hub · EMR

EMR.3: EMR security configs should encrypt at rest

Written and reviewed by Emnode · Last reviewed

What does AWS Security Hub EMR.3 check?

EMR.3 checks whether an EMR security configuration (`AWS::EMR::SecurityConfiguration`) enables encryption at rest. It reports FAILED when a security configuration exists but doesn't turn on at-rest encryption: the reusable template that decides this for a whole fleet of clusters.

Why does EMR.3 matter?

At-rest encryption covers three surfaces: data the job writes to S3 via EMRFS, the local disks used for scratch and HDFS (LUKS-encrypted EBS and ephemeral storage), and data persisted between stages. Leave it off and your shuffle files, HDFS blocks, and EMRFS objects sit in plaintext. EMR doesn't force you to attach a security configuration at all, so the cheapest path to "it works" is to run everything unencrypted: exactly the gap this catches.

How do I fix EMR.3?

  1. Audit every security configuration and which clusters use it.
  2. Author a new encrypted security configuration (existing ones are immutable, so you can't edit them).
  3. Roll clusters onto the new configuration without killing running jobs.
  4. Make encryption the launch-time default so it can't reappear.

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 EMR.3 a false positive?

EMR.3 is change-triggered against the AWS::EMR::SecurityConfiguration resource, so it evaluates every security configuration that exists in the account, including ones no running cluster references. A configuration you keep deliberately unencrypted for a throwaway, non-sensitive workload (a transient dev or benchmarking fleet that processes only synthetic or already-public data) will fail even though that's the intended state, and because configurations are immutable you can't simply toggle it on. The honest fix isn't to encrypt it but to confirm in inventory that nothing sensitive ever lands on clusters using it, then set the finding to SUPPRESSED with a note naming the configuration and the workload it serves, and delete the configuration outright once the work is done so a stale, plaintext template doesn't linger as a failing finding.

Part of the learning path Encrypt everything
  • EMR.1 An EMR primary node has a public IP
  • EMR.2 EMR account-level block public access is off
  • EMR.4 EMR security configs should encrypt in transit