EMR In-Transit and At-Rest Encryption
More Info:
Ensure that your AWS Elastic MapReduce (EMR) clusters are encrypted in order to meet security and compliance requirements. Data encryption helps prevent unauthorized users from reading sensitive data available on your EMR clusters and their associated data storage systems. This includes data saved to persistent media, known as data at-rest, and data that can be intercepted as it travels through the network, known as data in-transit.
Risk Level
High
Address
Security, Cost Optimization
Compliance Standards
HIPAA,GDPR,NIST,AWSWAF
Remediation
How to enable in transit and at rest encryption for EMR.
Using AWS Console
- Log in to the AWS Management Console using your AWS account credentials.
- Navigate to the Amazon EMR service by selecting "EMR" from the services menu. (In the Cloudanix Console, navigate to "Misconfig" page and look for Affected Assets for "EMR In-Transit and At-Rest Encryption" Policy.)
- Click on the "Create cluster" button to create a new EMR cluster or select an existing cluster to modify its settings.
- In the "Create Cluster" or "Cluster List" page, scroll down to the "Security and Encryption" section.
- Under the "Encryption" tab, you will find options for both in-transit and at-rest encryption.
- To enable in-transit encryption, select the "Enable" checkbox next to "Encryption in transit".
- Choose the desired encryption option for in-transit encryption. You can select "SSL" for encryption using SSL/TLS or "Custom" to provide your own custom encryption settings.
- To enable at-rest encryption, select the "Enable" checkbox next to "Encryption at rest".
- Choose the desired encryption option for at-rest encryption. You can select "Default AWS Key Management Service (KMS) key" or "Custom AWS KMS key" for encryption using AWS KMS. If you choose the "Custom AWS KMS key" option, provide the ARN (Amazon Resource Name) of the KMS key you want to use.
- Review the other configuration settings for your EMR cluster, such as instance types, storage, and software configuration.
- Click on the "Create cluster" or "Modify cluster" button to start the cluster creation or modification process.
- AWS will provision the EMR cluster with the specified encryption settings, enabling both in-transit and at-rest encryption.
Additional Reading
Triage and Remediation
- Remediation
Remediation
Using Console
Below are step‑by‑step console instructions to enable at‑rest and in‑transit encryption for Amazon Redshift.
1. At‑Rest Encryption (Redshift)
A. Check whether your existing cluster is encrypted
- Sign in to the AWS Management Console.
- Go to Amazon Redshift console.
- In the left pane, choose Clusters.
- Click your cluster identifier.
- On the Configuration tab, look for:
- Encryption: Enabled / Disabled
- KMS key: Which KMS key is used, if enabled.
If Encryption = Enabled, at‑rest encryption is already configured.
Note: Redshift cluster encryption cannot be turned on or off for an existing cluster. You must create a new encrypted cluster and move data.
B. Create or choose a KMS Customer Managed Key (optional but recommended)
If you don’t want to use the default AWS managed key:
- Open the AWS KMS console.
- Select Customer managed keys → Create key.
- Choose Symmetric → Next.
- Give it an alias (e.g.,
alias/redshift-encryption-key). - Configure key administrators and key usage permissions (grant Redshift account roles or IAM roles that will manage the cluster).
- Finish key creation.
C. Create a new encrypted Redshift cluster
- In the Redshift console, go to Clusters → Create cluster.
- Under Cluster configuration, set:
- Cluster identifier, Node type, number of nodes as needed.
- Under Database configurations, set admin username/password.
- Under Security and encryption (or similar section):
- Turn Encryption: On.
- KMS key: Select either:
- Default AWS Key for Redshift, or
- The customer managed key you created (e.g.,
alias/redshift-encryption-key).
- Configure networking/security groups as needed.
- Choose Create cluster.
This new cluster will now have encryption at rest enabled.
D. Move data from unencrypted to encrypted cluster
-
Option 1 – Snapshot and restore (if original is encrypted with a different key or you’re cloning an already‑encrypted one):
- For an unencrypted cluster you can’t create an encrypted snapshot directly; instead:
- Create a new encrypted cluster (done above),
- Use UNLOAD / COPY commands to migrate data.
- For an unencrypted cluster you can’t create an encrypted snapshot directly; instead:
-
Option 2 – UNLOAD / COPY:
- From the source (unencrypted) cluster:
- Use
UNLOADto export data to S3 (optionally encrypt S3 objects with SSE‑S3 or SSE‑KMS).
- Use
- From the target (encrypted) cluster:
- Use
COPYto load data from S3 into the new cluster.
- Use
- From the source (unencrypted) cluster:
-
After validation, point applications to the new encrypted cluster and decommission the old one.
2. In‑Transit Encryption (SSL/TLS) for Redshift
Redshift supports SSL/TLS for connections. You must:
- Ensure the cluster has SSL enabled (it is by default),
- Optionally enforce SSL in a parameter group,
- Update clients to use SSL.
A. Verify or configure SSL requirement via parameter group
- Go to the Redshift console → Parameter groups.
- Find the parameter group associated with your cluster:
- In Clusters → select cluster → Properties → note the Parameter group.
- If using the default parameter group:
- You cannot modify it. Create a new parameter group:
- Parameter groups → Create parameter group.
- Choose:
- Parameter group family matching your engine version.
- Group name and Description.
- Click Create.
- You cannot modify it. Create a new parameter group:
- Select your (new) parameter group → Edit parameters.
- Find parameter:
require_ssl.- Set Value to
true.
- Set Value to
- Save changes.
B. Attach the parameter group to the cluster
- In the Redshift console, go to Clusters.
- Select your cluster → Actions → Modify cluster.
- Under Database configurations (or Cluster properties):
- Set Parameter group to the new parameter group where
require_ssl = true.
- Set Parameter group to the new parameter group where
- Save/Apply changes and reboot the cluster if prompted:
- Cluster → Actions → Reboot (if not done automatically).
Once applied, the cluster will reject non‑SSL connections.
C. Ensure clients connect using SSL
For each application / client:
- Get cluster endpoint:
- Redshift console → Clusters → select cluster → General information → Endpoint.
- Use SSL-enabled connection strings.
Examples:
-
psql:
psql "host=<cluster-endpoint> port=5439 dbname=<db> user=<user> sslmode=require" -
JDBC URL:
jdbc:redshift://<cluster-endpoint>:5439/<db>?ssl=true&sslfactory=com.amazon.redshift.ssl.NonValidatingFactory -
ODBC:
- In DSN configuration, enable SSL or Require SSL.
- If you need certificate validation, download Redshift’s public certificate from AWS docs and configure client trust stores accordingly (optional but recommended).
3. Validate the Remediation
- At rest:
- Redshift console → Clusters → select cluster → Configuration:
- Confirm Encryption: Enabled and correct KMS key.
- Redshift console → Clusters → select cluster → Configuration:
- In transit:
- Confirm applications can only connect when SSL is enabled.
- Try a test connection without SSL and verify it fails.
This completes in‑transit and at‑rest encryption remediation for Amazon Redshift via the AWS console.
Using CLI
For Amazon Redshift, “in‑transit” = SSL, and “at‑rest” = KMS encryption on the cluster.
At‑rest encryption cannot be turned on for an existing unencrypted cluster; you must migrate to a new encrypted cluster.
Below are step‑by‑step AWS CLI instructions.
1. At‑Rest Encryption (Redshift)
1.1. Create (or identify) a KMS key
aws kms create-key --description "Redshift encryption key"
Output will include "KeyId": "arn:aws:kms:region:account-id:key/xxxxxxxx" – save this ARN.
Optionally add an alias:
aws kms create-alias \
--alias-name alias/redshift-kms \
--target-key-id <kms-key-id-or-arn>
You can then use alias/redshift-kms instead of the full ARN.
1.2. Snapshot your existing unencrypted cluster
Replace my-redshift-cluster and my-redshift-snapshot:
aws redshift create-cluster-snapshot \
--cluster-identifier my-redshift-cluster \
--snapshot-identifier my-redshift-snapshot
Wait until the snapshot is available:
aws redshift describe-cluster-snapshots \
--snapshot-identifier my-redshift-snapshot \
--query "Snapshots[0].Status"
1.3. Restore a new encrypted cluster from the snapshot
aws redshift restore-from-cluster-snapshot \
--cluster-identifier my-redshift-cluster-encrypted \
--snapshot-identifier my-redshift-snapshot \
--encrypted \
--kms-key-id alias/redshift-kms
You can also specify node type, security groups, etc., if you want to override snapshot defaults (optional):
aws redshift restore-from-cluster-snapshot \
--cluster-identifier my-redshift-cluster-encrypted \
--snapshot-identifier my-redshift-snapshot \
--encrypted \
--kms-key-id alias/redshift-kms \
--node-type ra3.xlplus \
--cluster-subnet-group-name my-subnet-group \
--vpc-security-group-ids sg-xxxxxxxx \
--publicly-accessible false
Wait until the new cluster is available:
aws redshift describe-clusters \
--cluster-identifier my-redshift-cluster-encrypted \
--query "Clusters[0].ClusterStatus"
1.4. Cut over and clean up
- Update applications to point to the new cluster’s endpoint (from
describe-clusters). - When fully migrated, delete the old unencrypted cluster:
aws redshift delete-cluster \
--cluster-identifier my-redshift-cluster \
--skip-final-cluster-snapshot
(Or omit --skip-final-cluster-snapshot and specify --final-cluster-snapshot-identifier if you want a final backup.)
2. In‑Transit Encryption (SSL) for Redshift
To enforce SSL, configure a parameter group and apply it to the cluster.
2.1. Create a parameter group (if you don’t already have a custom one)
aws redshift create-cluster-parameter-group \
--parameter-group-name my-redshift-ssl-pg \
--parameter-group-family redshift-1.0 \
--description "Require SSL for Redshift"
(Use redshift-1.0 or the family appropriate to your engine version.)
2.2. Set require_ssl to true
aws redshift modify-cluster-parameter-group \
--parameter-group-name my-redshift-ssl-pg \
--parameters "ParameterName=require_ssl,ParameterValue=true,Description=RequireSSL,ApplyType=static"
You can verify:
aws redshift describe-cluster-parameters \
--parameter-group-name my-redshift-ssl-pg \
--query "Parameters[?ParameterName=='require_ssl']"
2.3. Attach the parameter group to your (encrypted) cluster
aws redshift modify-cluster \
--cluster-identifier my-redshift-cluster-encrypted \
--cluster-parameter-group-name my-redshift-ssl-pg
You must reboot for static parameters to take effect:
aws redshift reboot-cluster \
--cluster-identifier my-redshift-cluster-encrypted
2.4. Ensure clients actually use SSL
Redshift will now require SSL, but your clients must be configured correctly:
- JDBC:
ssl=trueorsslmode=requirein the connection string. - ODBC: enable SSL / require SSL in DSN settings.
- psql:
sslmode=require(orverify-ca/verify-fullwith appropriate CA).
No extra CLI steps are needed here; this is client configuration.
3. Quick Verification
At‑rest encryption:
aws redshift describe-clusters \
--cluster-identifier my-redshift-cluster-encrypted \
--query "Clusters[0].[Encrypted,KmsKeyId]"
Should return true and the KMS key.
In‑transit (SSL) enforcement:
aws redshift describe-clusters \
--cluster-identifier my-redshift-cluster-encrypted \
--query "Clusters[0].ClusterParameterGroups"
Make sure my-redshift-ssl-pg is attached and ParameterApplyStatus is in-sync. Then test connections; non‑SSL connections should fail.
If you share your current cluster identifier and whether it’s already encrypted, I can tailor exact CLI commands for your environment.
Using Python
For Amazon Redshift, “in-transit” = SSL/TLS for client connections; “at-rest” = KMS-encrypted data on disk (cluster + snapshots).
Below is how to remediate both using Python (boto3).
Prereqs
pip install boto3
import boto3
redshift = boto3.client("redshift", region_name="us-east-1") # adjust region
Replace placeholders like <CLUSTER_IDENTIFIER>, <KMS_KEY_ARN> as needed.
1. At-Rest Encryption
A. New cluster (easiest)
You cannot enable encryption on an existing unencrypted cluster; you must create a new encrypted one and migrate.
- Create an encrypted snapshot of the old cluster (unencrypted snapshot → restore as encrypted).
# 1. Take snapshot of existing (unencrypted) cluster
snapshot_id = "old-cluster-snapshot"
redshift.create_cluster_snapshot(
SnapshotIdentifier=snapshot_id,
ClusterIdentifier="<OLD_CLUSTER_IDENTIFIER>"
)
- Wait for snapshot to be available (poll or use waiter):
waiter = redshift.get_waiter('snapshot_available')
waiter.wait(SnapshotIdentifier=snapshot_id)
- Restore snapshot to a new encrypted cluster:
redshift.restore_from_cluster_snapshot(
ClusterIdentifier="<NEW_ENCRYPTED_CLUSTER>",
SnapshotIdentifier=snapshot_id,
Encrypted=True,
KmsKeyId="<KMS_KEY_ARN>" # or omit to use AWS managed key
)
- Wait for new cluster to be available:
waiter = redshift.get_waiter('cluster_available')
waiter.wait(ClusterIdentifier="<NEW_ENCRYPTED_CLUSTER>")
- Update clients / apps / connection strings to point to the new cluster’s endpoint, test, then delete the old cluster:
redshift.delete_cluster(
ClusterIdentifier="<OLD_CLUSTER_IDENTIFIER>",
SkipFinalClusterSnapshot=True # or create final snapshot if needed
)
Now your data at rest (cluster & snapshots) is encrypted.
B. Ensuring snapshots are encrypted
For an already encrypted cluster, snapshots are encrypted automatically with the same KMS key.
To ensure cross-region snapshot copy is encrypted:
redshift.enable_snapshot_copy(
ClusterIdentifier="<ENCRYPTED_CLUSTER>",
DestinationRegion="us-west-2",
RetentionPeriod=7,
SnapshotCopyGrantName="<SNAPSHOT_COPY_GRANT_NAME>",
KmsKeyId="<DEST_REGION_KMS_KEY_ARN>"
)
2. In-Transit Encryption (SSL/TLS)
You enable and enforce SSL via a parameter group (require_ssl).
A. Create / update a parameter group with require_ssl=1
- Create a new parameter group (if you don’t want to modify an existing one):
param_group_name = "redshift-ssl-required"
redshift.create_cluster_parameter_group(
ParameterGroupName=param_group_name,
ParameterGroupFamily="redshift-1.0", # check your engine family
Description="Require SSL for all connections"
)
- Set
require_ssl = true(1):
redshift.modify_cluster_parameter_group(
ParameterGroupName=param_group_name,
Parameters=[
{
"ParameterName": "require_ssl",
"ParameterValue": "true", # or "1"
"Description": "Force SSL for all DB connections",
"Source": "user",
"DataType": "boolean",
"AllowedValues": "true,false",
"IsModifiable": True,
"ApplyType": "static"
}
]
)
require_sslis a static parameter → cluster must be rebooted after the parameter group is associated.
B. Attach the parameter group to your cluster
redshift.modify_cluster(
ClusterIdentifier="<CLUSTER_IDENTIFIER>",
ClusterParameterGroupName=param_group_name
)
Then reboot (or wait for Redshift to apply & manually reboot):
redshift.reboot_cluster(ClusterIdentifier="<CLUSTER_IDENTIFIER>")
3. Enforce SSL From Clients
After require_ssl is on, non-SSL connections will fail.
Make sure your Python clients use SSL, for example with psycopg2:
import psycopg2
conn = psycopg2.connect(
dbname="<DB_NAME>",
user="<USER>",
password="<PASSWORD>",
host="<REDSHIFT_ENDPOINT>",
port=5439,
sslmode="require" # or "verify-full" with CA bundle
)
Summary
- At rest (Redshift):
- Existing unencrypted: snapshot → restore encrypted cluster (with
Encrypted=True,KmsKeyId=...) → switch traffic → delete old cluster. - New clusters: always create with
Encrypted=True.
- Existing unencrypted: snapshot → restore encrypted cluster (with
- In transit:
- Create/modify parameter group: set
require_ssl=true. - Attach parameter group, reboot cluster.
- Ensure all clients connect with
sslmode=require(or stronger).
- Create/modify parameter group: set
Using Terraform
# At-rest encryption for an existing Redshift cluster
# NOTE: Changing `encrypted` from false→true forces replacement of the cluster
# (full recreate, data loss unless you restore from snapshot).
resource "aws_redshift_cluster" "this" {
cluster_identifier = "REDSHIFT_CLUSTER_IDENTIFIER" # e.g., "analytics-prod"
node_type = "dc2.large"
master_username = "MASTER_USERNAME"
master_password = "MASTER_PASSWORD"
# Enable encryption at rest
encrypted = true
# Optionally use a customer-managed KMS key (recommended)
# Omit this line to use the default Redshift KMS key
kms_key_id = "KMS_KEY_ARN_OR_ID"
# Attach the parameter group that enforces SSL (see below)
cluster_parameter_group_name = aws_redshift_parameter_group.ssl_enforced.name
# ...other required arguments (subnets, security groups, etc) ...
}
# In-transit encryption: enforce SSL for all connections
resource "aws_redshift_parameter_group" "ssl_enforced" {
name = "REDSHIFT_SSL_REQUIRED_PARAMETER_GROUP_NAME"
family = "redshift-1.0"
description = "Require SSL for all client connections"
parameter {
name = "require_ssl"
value = "true"
}
}
To verify, terraform plan should show encrypted = true, the desired kms_key_id on aws_redshift_cluster.this, and parameter.require_ssl changing/created as value = "true" on aws_redshift_parameter_group.ssl_enforced, with a note that the cluster will be replaced if it was previously unencrypted.