Skip to main content
emnode
Compliance Medium severity

AWS Security Hub · Opensearch

Opensearch.3: OpenSearch should encrypt node-to-node traffic

Written and reviewed by Emnode · Last reviewed

What does AWS Security Hub Opensearch.3 check?

Opensearch.3 fails when a domain does not have node-to-node encryption enabled. This is a separate layer from encryption at rest and from endpoint HTTPS; it secures the intra-cluster traffic of shard replication and query distribution between data nodes.

Why does Opensearch.3 matter?

Without node-to-node encryption, data moving between nodes inside the cluster (replicated shards and query results) crosses the network in plaintext. An attacker with a foothold on the VPC network could observe that traffic. Enabling it closes the one transport path that at-rest and endpoint encryption leave untouched.

How do I fix Opensearch.3?

  1. Read the domain's NodeToNodeEncryptionOptions to confirm it is off.
  2. Ensure the engine is Elasticsearch 6.7+ or any OpenSearch version, as enabling it on an existing domain requires at least that floor and older 5.x domains cannot support it.
  3. Enable it with a single update-domain-config flag, expecting a no-downtime blue/green deployment that may take minutes to hours.
  4. Add a Config rule so new domains are created with it on.

Remediation script · bash

# 1. Find unencrypted databases across engines (sample: RDS, Redshift, OpenSearch).
aws rds describe-db-instances \
  --query 'DBInstances[?StorageEncrypted==`false`].DBInstanceIdentifier' --output text
aws redshift describe-clusters \
  --query 'Clusters[?Encrypted==`false`].ClusterIdentifier' --output text

# 2. Immutable engine (RDS): snapshot, copy WITH a KMS key, restore the new instance.
SRC=prod-orders-db; KEY=alias/db-encryption
aws rds create-db-snapshot --db-instance-identifier $SRC --db-snapshot-identifier ${SRC}-snap
aws rds wait db-snapshot-completed --db-snapshot-identifier ${SRC}-snap
aws rds copy-db-snapshot \
  --source-db-snapshot-identifier ${SRC}-snap \
  --target-db-snapshot-identifier ${SRC}-snap-enc \
  --kms-key-id $KEY
aws rds wait db-snapshot-completed --db-snapshot-identifier ${SRC}-snap-enc
aws rds restore-db-instance-from-db-snapshot \
  --db-instance-identifier ${SRC}-enc --db-snapshot-identifier ${SRC}-snap-enc

# 3. In-place engine (Redshift): background migration (cluster is read-only during it).
aws redshift modify-cluster --cluster-identifier analytics-prod \
  --encrypted --kms-key-id $KEY

# 4. Prevent recurrence: deploy the rds-storage-encrypted Config rule to flag any
#    new unencrypted RDS instance (back it with an SCP to deny creation outright).
aws configservice put-config-rule --config-rule '{
  "ConfigRuleName": "rds-storage-encrypted",
  "Source": {"Owner": "AWS", "SourceIdentifier": "RDS_STORAGE_ENCRYPTED"}
}'

Full walkthrough (console steps, edge cases and verification) in the lesson Encrypt AWS databases at rest.

Is Opensearch.3 a false positive?

Because enabling it triggers a blue/green rebuild rather than an instant toggle, teams sometimes assume the change failed when the domain shows Processing for a long time: it is working, just copying every shard across new nodes.

Part of the learning path Encrypt everything